summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkeishi@chromium.org <keishi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-07 02:56:17 +0000
committerkeishi@chromium.org <keishi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-07 02:56:17 +0000
commit6e08bfb743b8dcf8b7ae3052c685b0ef284aa737 (patch)
tree0b3ecd219a0cf41f798afee689360ac630b965fa
parent14e864b164494e7c3dae5a53d2956eef91b1f19f (diff)
downloadchromium_src-6e08bfb743b8dcf8b7ae3052c685b0ef284aa737.zip
chromium_src-6e08bfb743b8dcf8b7ae3052c685b0ef284aa737.tar.gz
chromium_src-6e08bfb743b8dcf8b7ae3052c685b0ef284aa737.tar.bz2
Support datalist for date/time input types on Android
BUG=242455 Review URL: https://codereview.chromium.org/23623019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@239290 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/android/date_time_chooser_android.cc48
-rw-r--r--content/browser/android/date_time_chooser_android.h5
-rw-r--r--content/browser/web_contents/web_contents_impl.cc3
-rw-r--r--content/common/date_time_suggestion.h31
-rw-r--r--content/common/view_messages.h8
-rw-r--r--content/content_common.gypi1
-rw-r--r--content/content_renderer.gypi2
-rw-r--r--content/public/android/java/resource_map/org/chromium/content/R.java5
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/input/DateDialogNormalizer.java20
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java31
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/input/DateTimeSuggestion.java59
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/input/DateTimeSuggestionListAdapter.java56
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java109
-rw-r--r--content/public/android/java/strings/android_content_strings.grd7
-rw-r--r--content/public/android/javatests/src/org/chromium/content/browser/input/InputDialogContainerTest.java40
-rw-r--r--content/renderer/date_time_suggestion_builder.cc22
-rw-r--r--content/renderer/date_time_suggestion_builder.h23
-rw-r--r--content/renderer/renderer_date_time_picker.cc5
-rw-r--r--ui/android/java/res/layout/date_time_suggestion.xml35
19 files changed, 454 insertions, 56 deletions
diff --git a/content/browser/android/date_time_chooser_android.cc b/content/browser/android/date_time_chooser_android.cc
index 87f02b9f..f6b50c9 100644
--- a/content/browser/android/date_time_chooser_android.cc
+++ b/content/browser/android/date_time_chooser_android.cc
@@ -4,17 +4,41 @@
#include "content/browser/android/date_time_chooser_android.h"
+#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
+#include "base/i18n/char_iterator.h"
+#include "content/common/date_time_suggestion.h"
#include "content/common/view_messages.h"
#include "content/public/browser/android/content_view_core.h"
#include "content/public/browser/render_view_host.h"
#include "jni/DateTimeChooserAndroid_jni.h"
+#include "third_party/icu/source/common/unicode/uchar.h"
+#include "third_party/icu/source/common/unicode/unistr.h"
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF16;
using base::android::ConvertUTF8ToJavaString;
+using base::android::ConvertUTF16ToJavaString;
+namespace {
+
+string16 SanitizeSuggestionString(const string16& string) {
+ string16 trimmed = string.substr(0, 255);
+ icu::UnicodeString sanitized;
+ base::i18n::UTF16CharIterator sanitized_iterator(&trimmed);
+ while (!sanitized_iterator.end()) {
+ UChar c = sanitized_iterator.get();
+ if (u_isprint(c))
+ sanitized.append(c);
+ sanitized_iterator.Advance();
+ }
+ return string16(sanitized.getBuffer(),
+ static_cast<size_t>(sanitized.length()));
+}
+
+} // namespace
+
namespace content {
// DateTimeChooserAndroid implementation
@@ -55,10 +79,29 @@ void DateTimeChooserAndroid::ShowDialog(
double dialog_value,
double min,
double max,
- double step) {
+ double step,
+ const std::vector<DateTimeSuggestion>& suggestions) {
host_ = host;
JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobjectArray> suggestions_array;
+
+ if (suggestions.size() > 0) {
+ suggestions_array =
+ Java_DateTimeChooserAndroid_createSuggestionsArray(env,
+ suggestions.size());
+ for (size_t i = 0; i < suggestions.size(); ++i) {
+ const content::DateTimeSuggestion& suggestion = suggestions[i];
+ ScopedJavaLocalRef<jstring> localized_value = ConvertUTF16ToJavaString(
+ env, SanitizeSuggestionString(suggestion.localized_value));
+ ScopedJavaLocalRef<jstring> label = ConvertUTF16ToJavaString(
+ env, SanitizeSuggestionString(suggestion.label));
+ Java_DateTimeChooserAndroid_setDateTimeSuggestionAt(env,
+ suggestions_array.obj(), i,
+ suggestion.value, localized_value.obj(), label.obj());
+ }
+ }
+
j_date_time_chooser_.Reset(Java_DateTimeChooserAndroid_createDateTimeChooser(
env,
content->GetJavaObject().obj(),
@@ -67,7 +110,8 @@ void DateTimeChooserAndroid::ShowDialog(
dialog_value,
min,
max,
- step));
+ step,
+ suggestions_array.obj()));
}
// ----------------------------------------------------------------------------
diff --git a/content/browser/android/date_time_chooser_android.h b/content/browser/android/date_time_chooser_android.h
index a04850f..c02ecf5 100644
--- a/content/browser/android/date_time_chooser_android.h
+++ b/content/browser/android/date_time_chooser_android.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_ANDROID_DATE_TIME_CHOOSER_ANDROID_H_
#include <string>
+#include <vector>
#include "base/android/jni_helper.h"
#include "base/memory/scoped_ptr.h"
@@ -15,6 +16,7 @@ namespace content {
class ContentViewCore;
class RenderViewHost;
+struct DateTimeSuggestion;
// Android implementation for DateTimeChooser dialogs.
class DateTimeChooserAndroid {
@@ -31,7 +33,8 @@ class DateTimeChooserAndroid {
double dialog_value,
double min,
double max,
- double step);
+ double step,
+ const std::vector<DateTimeSuggestion>& suggestions);
// Replaces the current value
void ReplaceDateTime(JNIEnv* env, jobject, jdouble value);
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index bb681ed..81edfed 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2376,7 +2376,8 @@ void WebContentsImpl::OnOpenDateTimeDialog(
value.dialog_value,
value.minimum,
value.maximum,
- value.step);
+ value.step,
+ value.suggestions);
}
void WebContentsImpl::OnJavaBridgeGetChannelHandle(IPC::Message* reply_msg) {
diff --git a/content/common/date_time_suggestion.h b/content/common/date_time_suggestion.h
new file mode 100644
index 0000000..ce35430
--- /dev/null
+++ b/content/common/date_time_suggestion.h
@@ -0,0 +1,31 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_DATE_TIME_SUGGESTION_H_
+#define CONTENT_COMMON_DATE_TIME_SUGGESTION_H_
+
+#include <vector>
+
+#include "base/strings/string16.h"
+#include "content/common/content_export.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace content {
+
+// Container for information about datalist suggestion for the date/time input
+// control. Keep in sync with DateTimeSuggestion.java
+struct CONTENT_EXPORT DateTimeSuggestion {
+ DateTimeSuggestion() {}
+
+ // The date/time value represented as a double.
+ double value;
+ // The localized value to be shown to the user.
+ base::string16 localized_value;
+ // The label for the suggestion.
+ base::string16 label;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_DATE_TIME_SUGGESTION_H_
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index a5dc8b9..edf8337 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -35,6 +35,7 @@
#include "content/public/common/stop_find_action.h"
#include "content/public/common/three_d_api_types.h"
#include "content/public/common/window_container_type.h"
+#include "content/common/date_time_suggestion.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_platform_file.h"
@@ -165,6 +166,12 @@ IPC_STRUCT_TRAITS_BEGIN(content::ColorSuggestion)
IPC_STRUCT_TRAITS_MEMBER(label)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(content::DateTimeSuggestion)
+ IPC_STRUCT_TRAITS_MEMBER(value)
+ IPC_STRUCT_TRAITS_MEMBER(localized_value)
+ IPC_STRUCT_TRAITS_MEMBER(label)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(content::ContextMenuParams)
IPC_STRUCT_TRAITS_MEMBER(media_type)
IPC_STRUCT_TRAITS_MEMBER(x)
@@ -404,6 +411,7 @@ IPC_STRUCT_BEGIN(ViewHostMsg_DateTimeDialogValue_Params)
IPC_STRUCT_MEMBER(double, minimum)
IPC_STRUCT_MEMBER(double, maximum)
IPC_STRUCT_MEMBER(double, step)
+ IPC_STRUCT_MEMBER(std::vector<content::DateTimeSuggestion>, suggestions)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(ViewHostMsg_DidFailProvisionalLoadWithError_Params)
diff --git a/content/content_common.gypi b/content/content_common.gypi
index e49acba..395b710 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -152,6 +152,7 @@
'common/cookie_data.cc',
'common/cookie_data.h',
'common/database_messages.h',
+ 'common/date_time_suggestion.h',
'common/desktop_notification_messages.h',
'common/device_orientation/device_motion_hardware_buffer.h',
'common/device_orientation/device_motion_messages.h',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 0dad876..8b949de 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -102,6 +102,8 @@
'renderer/context_menu_params_builder.h',
'renderer/cursor_utils.cc',
'renderer/cursor_utils.h',
+ 'renderer/date_time_suggestion_builder.cc',
+ 'renderer/date_time_suggestion_builder.h',
'renderer/device_orientation/device_motion_event_pump.cc',
'renderer/device_orientation/device_motion_event_pump.h',
'renderer/device_orientation/device_orientation_event_pump.cc',
diff --git a/content/public/android/java/resource_map/org/chromium/content/R.java b/content/public/android/java/resource_map/org/chromium/content/R.java
index 44d0859..ac39779 100644
--- a/content/public/android/java/resource_map/org/chromium/content/R.java
+++ b/content/public/android/java/resource_map/org/chromium/content/R.java
@@ -29,6 +29,8 @@ public final class R {
public static final class id {
public static int ampm;
public static int date_picker;
+ public static int date_time_suggestion_value;
+ public static int date_time_suggestion_label;
public static int hour;
public static int milli;
public static int minute;
@@ -48,6 +50,7 @@ public final class R {
}
public static final class layout {
public static int date_time_picker_dialog;
+ public static int date_time_suggestion;
public static int two_field_date_picker;
public static int multi_field_time_picker_dialog;
}
@@ -66,6 +69,7 @@ public final class R {
public static int date_picker_dialog_clear;
public static int date_picker_dialog_set;
public static int date_picker_dialog_title;
+ public static int date_picker_dialog_other_button_label;
public static int date_time_picker_dialog_title;
public static int media_player_error_button;
public static int media_player_error_text_invalid_progressive_playback;
@@ -82,6 +86,7 @@ public final class R {
public static int time_picker_dialog_minute_second_separator;
public static int time_picker_dialog_second_subsecond_separator;
public static int time_picker_dialog_pm;
+ public static int time_picker_dialog_title;
public static int week_picker_dialog_title;
}
public static final class style {
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/DateDialogNormalizer.java b/content/public/android/java/src/org/chromium/content/browser/input/DateDialogNormalizer.java
index 4634808..709d0e7 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/DateDialogNormalizer.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/DateDialogNormalizer.java
@@ -15,15 +15,15 @@ import java.util.TimeZone;
*/
class DateDialogNormalizer {
- private static void setLimits(DatePicker picker, long min, long max) {
+ private static void setLimits(DatePicker picker, long minMillis, long maxMillis) {
// DatePicker intervals are non inclusive, the DatePicker will throw an
// exception when setting the min/max attribute to the current date
// so make sure this never happens
- if (max <= min) {
+ if (maxMillis <= minMillis) {
return;
}
- Calendar minCal = trimToDate(min);
- Calendar maxCal = trimToDate(max);
+ Calendar minCal = trimToDate(minMillis);
+ Calendar maxCal = trimToDate(maxMillis);
int currentYear = picker.getYear();
int currentMonth = picker.getMonth();
int currentDayOfMonth = picker.getDayOfMonth();
@@ -57,21 +57,21 @@ class DateDialogNormalizer {
* needed to comply with the {@code min} and {@code max} attributes.
*/
static void normalize(DatePicker picker, OnDateChangedListener listener,
- int year, int month, int day, int hour, int minute, long min, long max) {
+ int year, int month, int day, int hour, int minute, long minMillis, long maxMillis) {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
calendar.clear();
calendar.set(year, month, day, hour, minute, 0);
- if (calendar.getTimeInMillis() < min) {
+ if (calendar.getTimeInMillis() < minMillis) {
calendar.clear();
- calendar.setTimeInMillis(min);
- } else if (calendar.getTimeInMillis() > max) {
+ calendar.setTimeInMillis(minMillis);
+ } else if (calendar.getTimeInMillis() > maxMillis) {
calendar.clear();
- calendar.setTimeInMillis(max);
+ calendar.setTimeInMillis(maxMillis);
}
picker.init(
calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH), listener);
- setLimits(picker, min, max);
+ setLimits(picker, minMillis, maxMillis);
}
}
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java b/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java
index a45bc57..8cc41ff9 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java
@@ -38,8 +38,9 @@ class DateTimeChooserAndroid {
}
private void showDialog(int dialogType, double dialogValue,
- double min, double max, double step) {
- mInputDialogContainer.showDialog(dialogType, dialogValue, min, max, step);
+ double min, double max, double step,
+ DateTimeSuggestion[] suggestions) {
+ mInputDialogContainer.showDialog(dialogType, dialogValue, min, max, step, suggestions);
}
@CalledByNative
@@ -47,21 +48,41 @@ class DateTimeChooserAndroid {
ContentViewCore contentViewCore,
long nativeDateTimeChooserAndroid,
int dialogType, double dialogValue,
- double min, double max, double step) {
+ double min, double max, double step,
+ DateTimeSuggestion[] suggestions) {
DateTimeChooserAndroid chooser =
new DateTimeChooserAndroid(
contentViewCore.getContext(),
nativeDateTimeChooserAndroid);
- chooser.showDialog(dialogType, dialogValue, min, max, step);
+ chooser.showDialog(dialogType, dialogValue, min, max, step, suggestions);
return chooser;
}
@CalledByNative
+ private static DateTimeSuggestion[] createSuggestionsArray(int size) {
+ return new DateTimeSuggestion[size];
+ }
+
+ /**
+ * @param array DateTimeSuggestion array that should get a new suggestion set.
+ * @param index Index in the array where to place a new suggestion.
+ * @param value Value of the suggestion.
+ * @param localizedValue Localized value of the suggestion.
+ * @param label Label of the suggestion.
+ */
+ @CalledByNative
+ private static void setDateTimeSuggestionAt(DateTimeSuggestion[] array, int index,
+ double value, String localizedValue, String label) {
+ array[index] = new DateTimeSuggestion(value, localizedValue, label);
+ }
+
+ @CalledByNative
private static void initializeDateInputTypes(
int textInputTypeDate, int textInputTypeDateTime,
int textInputTypeDateTimeLocal, int textInputTypeMonth,
int textInputTypeTime, int textInputTypeWeek) {
- InputDialogContainer.initializeInputTypes(textInputTypeDate,
+ InputDialogContainer.initializeInputTypes(
+ textInputTypeDate,
textInputTypeDateTime, textInputTypeDateTimeLocal,
textInputTypeMonth, textInputTypeTime, textInputTypeWeek);
}
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/DateTimeSuggestion.java b/content/public/android/java/src/org/chromium/content/browser/input/DateTimeSuggestion.java
new file mode 100644
index 0000000..5416c31
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/input/DateTimeSuggestion.java
@@ -0,0 +1,59 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser.input;
+
+/**
+ * Date/time suggestion container used to store information for each suggestion that will be shown
+ * in the suggestion list dialog. Keep in sync with date_time_suggestion.h.
+ */
+class DateTimeSuggestion {
+ private final double mValue;
+ private final String mLocalizedValue;
+ private final String mLabel;
+
+ /**
+ * Constructs a color suggestion container.
+ * @param value The suggested date/time value.
+ * @param localizedValue The suggested value localized.
+ * @param label The label for the suggestion.
+ */
+ DateTimeSuggestion(double value, String localizedValue, String label) {
+ mValue = value;
+ mLocalizedValue = localizedValue;
+ mLabel = label;
+ }
+
+ double value() {
+ return mValue;
+ }
+
+ String localizedValue() {
+ return mLocalizedValue;
+ }
+
+ String label() {
+ return mLabel;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (!(object instanceof DateTimeSuggestion)) {
+ return false;
+ }
+ final DateTimeSuggestion other = (DateTimeSuggestion) object;
+ return mValue == other.mValue &&
+ mLocalizedValue == other.mLocalizedValue &&
+ mLabel == other.mLabel;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 31;
+ hash = 37 * hash + (int) mValue;
+ hash = 37 * hash + mLocalizedValue.hashCode();
+ hash = 37 * hash + mLabel.hashCode();
+ return hash;
+ }
+}
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/DateTimeSuggestionListAdapter.java b/content/public/android/java/src/org/chromium/content/browser/input/DateTimeSuggestionListAdapter.java
new file mode 100644
index 0000000..7e6a980
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/input/DateTimeSuggestionListAdapter.java
@@ -0,0 +1,56 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+package org.chromium.content.browser.input;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+import org.chromium.content.R;
+
+import java.util.List;
+
+/**
+ * Date/time suggestion adapter for the suggestion dialog.
+ */
+class DateTimeSuggestionListAdapter extends ArrayAdapter<DateTimeSuggestion> {
+ private final Context mContext;
+
+ DateTimeSuggestionListAdapter(Context context, List<DateTimeSuggestion> objects) {
+ super(context, R.layout.date_time_suggestion, objects);
+ mContext = context;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View layout = convertView;
+ if (convertView == null) {
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ layout = inflater.inflate(R.layout.date_time_suggestion, parent, false);
+ }
+ TextView labelView = (TextView) layout.findViewById(R.id.date_time_suggestion_value);
+ TextView sublabelView = (TextView) layout.findViewById(R.id.date_time_suggestion_label);
+
+ if (position == getCount() - 1) {
+ labelView.setText(mContext.getText(R.string.date_picker_dialog_other_button_label));
+ sublabelView.setText("");
+ } else {
+ labelView.setText(getItem(position).localizedValue());
+ sublabelView.setText(getItem(position).label());
+ }
+
+ return layout;
+ }
+
+ @Override
+ public int getCount() {
+ return super.getCount() + 1;
+ }
+}
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java b/content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java
index 7ec81cb..22ebfef 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/InputDialogContainer.java
@@ -13,13 +13,19 @@ import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.text.format.DateFormat;
import android.text.format.Time;
+import android.view.View;
+import android.widget.AdapterView;
import android.widget.DatePicker;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+import android.widget.TextView;
import android.widget.TimePicker;
import org.chromium.content.R;
import org.chromium.content.browser.input.DateTimePickerDialog.OnDateTimeSetListener;
import org.chromium.content.browser.input.MultiFieldTimePickerDialog.OnMultiFieldTimeSetListener;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
@@ -71,7 +77,7 @@ public class InputDialogContainer {
mInputActionDelegate = inputActionDelegate;
}
- void showDialog(final int dialogType, double dialogValue,
+ void showPickerDialog(final int dialogType, double dialogValue,
double min, double max, double step) {
Calendar cal;
// |dialogValue|, |min|, |max| mean different things depending on the |dialogType|.
@@ -98,19 +104,19 @@ public class InputDialogContainer {
}
}
if (dialogType == sTextInputTypeDate) {
- showDialog(dialogType,
+ showPickerDialog(dialogType,
cal.get(Calendar.YEAR),
cal.get(Calendar.MONTH),
cal.get(Calendar.DAY_OF_MONTH),
0, 0, 0, 0, 0, min, max, step);
} else if (dialogType == sTextInputTypeTime) {
- showDialog(dialogType, 0, 0, 0,
+ showPickerDialog(dialogType, 0, 0, 0,
cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE),
0, 0, 0, min, max, step);
} else if (dialogType == sTextInputTypeDateTime ||
dialogType == sTextInputTypeDateTimeLocal) {
- showDialog(dialogType,
+ showPickerDialog(dialogType,
cal.get(Calendar.YEAR),
cal.get(Calendar.MONTH),
cal.get(Calendar.DAY_OF_MONTH),
@@ -120,16 +126,89 @@ public class InputDialogContainer {
cal.get(Calendar.MILLISECOND),
0, min, max, step);
} else if (dialogType == sTextInputTypeMonth) {
- showDialog(dialogType, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 0,
+ showPickerDialog(dialogType, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), 0,
0, 0, 0, 0, 0, min, max, step);
} else if (dialogType == sTextInputTypeWeek) {
int year = WeekPicker.getISOWeekYearForDate(cal);
int week = WeekPicker.getWeekForDate(cal);
- showDialog(dialogType, year, 0, 0, 0, 0, 0, 0, week, min, max, step);
+ showPickerDialog(dialogType, year, 0, 0, 0, 0, 0, 0, week, min, max, step);
}
}
- void showDialog(final int dialogType,
+ void showSuggestionDialog(final int dialogType,
+ final double dialogValue,
+ final double min, final double max, final double step,
+ DateTimeSuggestion[] suggestions) {
+ ListView suggestionListView = new ListView(mContext);
+ final DateTimeSuggestionListAdapter adapter =
+ new DateTimeSuggestionListAdapter(mContext, Arrays.asList(suggestions));
+ suggestionListView.setAdapter(adapter);
+ suggestionListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if (position == adapter.getCount() - 1) {
+ dismissDialog();
+ showPickerDialog(dialogType, dialogValue, min, max, step);
+ } else {
+ double suggestionValue = adapter.getItem(position).value();
+ mInputActionDelegate.replaceDateTime(suggestionValue);
+ dismissDialog();
+ mDialogAlreadyDismissed = true;
+ }
+ }
+ });
+
+ int dialogTitleId = R.string.date_picker_dialog_title;
+ if (dialogType == sTextInputTypeTime) {
+ dialogTitleId = R.string.time_picker_dialog_title;
+ } else if (dialogType == sTextInputTypeDateTime ||
+ dialogType == sTextInputTypeDateTimeLocal) {
+ dialogTitleId = R.string.date_time_picker_dialog_title;
+ } else if (dialogType == sTextInputTypeMonth) {
+ dialogTitleId = R.string.month_picker_dialog_title;
+ } else if (dialogType == sTextInputTypeWeek) {
+ dialogTitleId = R.string.week_picker_dialog_title;
+ }
+
+ mDialog = new AlertDialog.Builder(mContext)
+ .setTitle(dialogTitleId)
+ .setView(suggestionListView)
+ .setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ if (mDialog == dialog && !mDialogAlreadyDismissed) {
+ mDialogAlreadyDismissed = true;
+ mInputActionDelegate.cancelDateTimeDialog();
+ }
+ }
+ })
+ .setNegativeButton(mContext.getText(android.R.string.cancel),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dismissDialog();
+ }
+ })
+ .create();
+
+ mDialogAlreadyDismissed = false;
+ mDialog.show();
+ }
+
+ void showDialog(final int type, final double value,
+ double min, double max, double step,
+ DateTimeSuggestion[] suggestions) {
+ // When the web page asks to show a dialog while there is one already open,
+ // dismiss the old one.
+ dismissDialog();
+ if (suggestions == null) {
+ showPickerDialog(type, value, min, max, step);
+ } else {
+ showSuggestionDialog(type, value, min, max, step, suggestions);
+ }
+ }
+
+ void showPickerDialog(final int dialogType,
int year, int month, int monthDay,
int hourOfDay, int minute, int second, int millis, int week,
double min, double max, double step) {
@@ -293,14 +372,14 @@ public class InputDialogContainer {
millis);
} else {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
- cal.clear();
- cal.set(Calendar.YEAR, year);
- cal.set(Calendar.MONTH, month);
- cal.set(Calendar.DAY_OF_MONTH, monthDay);
- cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
- cal.set(Calendar.MINUTE, minute);
- cal.set(Calendar.SECOND, second);
- cal.set(Calendar.MILLISECOND, millis);
+ cal.clear();
+ cal.set(Calendar.YEAR, year);
+ cal.set(Calendar.MONTH, month);
+ cal.set(Calendar.DAY_OF_MONTH, monthDay);
+ cal.set(Calendar.HOUR_OF_DAY, hourOfDay);
+ cal.set(Calendar.MINUTE, minute);
+ cal.set(Calendar.SECOND, second);
+ cal.set(Calendar.MILLISECOND, millis);
mInputActionDelegate.replaceDateTime((double) cal.getTimeInMillis());
}
}
diff --git a/content/public/android/java/strings/android_content_strings.grd b/content/public/android/java/strings/android_content_strings.grd
index 2ec7d77..580dd79 100644
--- a/content/public/android/java/strings/android_content_strings.grd
+++ b/content/public/android/java/strings/android_content_strings.grd
@@ -11,14 +11,17 @@
<message desc="Content description for the content view that holds the web contents [CHAR-LIMIT=32]" name="IDS_ACCESSIBILITY_CONTENT_VIEW">
Web View
</message>
+ <message desc="Title for the date picker dialog, which can be used to choose a date. [CHAR-LIMIT=32]" name="IDS_DATE_PICKER_DIALOG_TITLE">
+ Set date
+ </message>
<message desc="Label for 'set' button in date picker dialog and time picker dialog, used to replace the contents of a field with the chosen date or time [CHAR-LIMIT=12]" name="IDS_DATE_PICKER_DIALOG_SET">
Set
</message>
<message desc="Label for 'clear' button in date picker dialog and time picker dialog, used to replace the contents of a field with the empty string [CHAR-LIMIT=12]" name="IDS_DATE_PICKER_DIALOG_CLEAR">
Clear
</message>
- <message desc="Title for the date picker dialog, which can be used to choose a date. [CHAR-LIMIT=32]" name="IDS_DATE_PICKER_DIALOG_TITLE">
- Set date
+ <message desc="Label for 'other' button in date picker dialog and time picker dialog, used to close the list of suggestions and open the the full date/time picker [CHAR-LIMIT=32]" name="IDS_DATE_PICKER_DIALOG_OTHER_BUTTON_LABEL">
+ Other
</message>
<message desc="Title for the date/time picker dialog, which can be used to choose a date and time. [CHAR-LIMIT=32]" name="IDS_DATE_TIME_PICKER_DIALOG_TITLE">
Set date and time
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/InputDialogContainerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/InputDialogContainerTest.java
index 235a859..003a92f 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/input/InputDialogContainerTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/input/InputDialogContainerTest.java
@@ -54,28 +54,28 @@ public class InputDialogContainerTest extends AndroidTestCase {
1970, 0, 1,
0, 0, 0, 0, 0,
DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATE, 0.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_DATE, 0.0,
DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0);
mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_DATE,
1, 0, 1,
0, 0, 0, 0, 0,
DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATE, -62135596800000.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_DATE, -62135596800000.0,
DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0);
mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_DATE,
275760, 8, 13,
0, 0, 0, 0, 0,
DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATE, 8640000000000000.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_DATE, 8640000000000000.0,
DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0);
mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_DATE,
2013, 10, 7,
0, 0, 0, 0, 0,
DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATE, 1383782400000.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_DATE, 1383782400000.0,
DATE_DIALOG_DEFAULT_MIN, DATE_DIALOG_DEFAULT_MAX, 1.0);
}
@@ -86,28 +86,28 @@ public class InputDialogContainerTest extends AndroidTestCase {
1970, 0, 1,
0, 0, 0, 0, 0,
DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATETIMELOCAL, 0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_DATETIMELOCAL, 0,
DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 1.0);
mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_DATETIMELOCAL,
1, 0, 1,
0, 0, 0, 0, 0,
DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATETIMELOCAL, -62135596800000.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_DATETIMELOCAL, -62135596800000.0,
DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 1.0);
mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_DATETIMELOCAL,
275760, 8, 13,
0, 0, 0, 0, 0,
DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATETIMELOCAL, 8640000000000000.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_DATETIMELOCAL, 8640000000000000.0,
DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 1.0);
mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_DATETIMELOCAL,
2013, 10, 8,
1, 1, 2, 196, 0,
DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 0.001);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_DATETIMELOCAL, 1383872462196.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_DATETIMELOCAL, 1383872462196.0,
DATETIMELOCAL_DIALOG_DEFAULT_MIN, DATETIMELOCAL_DIALOG_DEFAULT_MAX, 0.001);
}
@@ -118,28 +118,28 @@ public class InputDialogContainerTest extends AndroidTestCase {
1970, 0, 0,
0, 0, 0, 0, 0,
MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_MONTH, 0.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_MONTH, 0.0,
MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0);
mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_MONTH,
1, 0, 0,
0, 0, 0, 0, 0,
MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_MONTH, -23628.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_MONTH, -23628.0,
MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0);
mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_MONTH,
275760, 8, 0,
0, 0, 0, 0, 0,
MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_MONTH, 3285488.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_MONTH, 3285488.0,
MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0);
mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_MONTH,
2013, 10, 0,
0, 0, 0, 0, 0,
MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_MONTH, 526.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_MONTH, 526.0,
MONTH_DIALOG_DEFAULT_MIN, MONTH_DIALOG_DEFAULT_MAX, 1.0);
}
@@ -150,7 +150,7 @@ public class InputDialogContainerTest extends AndroidTestCase {
0, 0, 0,
0, 0, 0, 0, 0,
TIME_DIALOG_DEFAULT_MIN, TIME_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_TIME, 0.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_TIME, 0.0,
TIME_DIALOG_DEFAULT_MIN, TIME_DIALOG_DEFAULT_MAX, 1.0);
// Time dialog only shows the hour and minute fields.
@@ -158,14 +158,14 @@ public class InputDialogContainerTest extends AndroidTestCase {
0, 0, 0,
23, 59, 0, 0, 0,
TIME_DIALOG_DEFAULT_MIN, TIME_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_TIME, 86399999.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_TIME, 86399999.0,
TIME_DIALOG_DEFAULT_MIN, TIME_DIALOG_DEFAULT_MAX, 1.0);
mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_TIME,
0, 0, 0,
15, 23, 0, 0, 0,
TIME_DIALOG_DEFAULT_MIN, TIME_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_TIME, 55425678.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_TIME, 55425678.0,
TIME_DIALOG_DEFAULT_MIN, TIME_DIALOG_DEFAULT_MAX, 1.0);
}
@@ -176,28 +176,28 @@ public class InputDialogContainerTest extends AndroidTestCase {
1970, 0, 0,
0, 0, 0, 0, 1,
WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_WEEK, -259200000.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_WEEK, -259200000.0,
WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0);
mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_WEEK,
1, 0, 0,
0, 0, 0, 0, 1,
WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_WEEK, -62135596800000.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_WEEK, -62135596800000.0,
WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0);
mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_WEEK,
275760, 0, 0,
0, 0, 0, 0, 37,
WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_WEEK, 8639999568000000.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_WEEK, 8639999568000000.0,
WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0);
mInputDialogContainer.setShowDialogExpectation(TEXT_INPUT_TYPE_WEEK,
2013, 0, 0,
0, 0, 0, 0, 44,
WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0);
- mInputDialogContainer.showDialog(TEXT_INPUT_TYPE_WEEK, 1382918400000.0,
+ mInputDialogContainer.showPickerDialog(TEXT_INPUT_TYPE_WEEK, 1382918400000.0,
WEEK_DIALOG_DEFAULT_MIN, WEEK_DIALOG_DEFAULT_MAX, 1.0);
}
@@ -373,7 +373,7 @@ public class InputDialogContainerTest extends AndroidTestCase {
}
@Override
- void showDialog(final int dialogType,
+ void showPickerDialog(final int dialogType,
int year, int month, int monthDay,
int hourOfDay, int minute, int second, int millis, int week,
double min, double max, double step) {
diff --git a/content/renderer/date_time_suggestion_builder.cc b/content/renderer/date_time_suggestion_builder.cc
new file mode 100644
index 0000000..7dff00d
--- /dev/null
+++ b/content/renderer/date_time_suggestion_builder.cc
@@ -0,0 +1,22 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/date_time_suggestion_builder.h"
+
+#include "content/common/date_time_suggestion.h"
+#include "third_party/WebKit/public/web/WebDateTimeSuggestion.h"
+
+namespace content {
+
+// static
+DateTimeSuggestion DateTimeSuggestionBuilder::Build(
+ const blink::WebDateTimeSuggestion& suggestion) {
+ DateTimeSuggestion result;
+ result.value = suggestion.value;
+ result.localized_value = suggestion.localizedValue;
+ result.label = suggestion.label;
+ return result;
+}
+
+} // namespace content
diff --git a/content/renderer/date_time_suggestion_builder.h b/content/renderer/date_time_suggestion_builder.h
new file mode 100644
index 0000000..5087051
--- /dev/null
+++ b/content/renderer/date_time_suggestion_builder.h
@@ -0,0 +1,23 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_DATE_TIME_SUGGESTION_BUILDER_H_
+#define CONTENT_RENDERER_DATE_TIME_SUGGESTION_BUILDER_H_
+
+namespace blink {
+struct WebDateTimeSuggestion;
+} // namespace blink
+
+namespace content {
+struct DateTimeSuggestion;
+
+class DateTimeSuggestionBuilder {
+ public:
+ static DateTimeSuggestion Build(
+ const blink::WebDateTimeSuggestion& suggestion);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_DATE_TIME_SUGGESTION_BUILDER_H_
diff --git a/content/renderer/renderer_date_time_picker.cc b/content/renderer/renderer_date_time_picker.cc
index 8c3a8f2..592e249 100644
--- a/content/renderer/renderer_date_time_picker.cc
+++ b/content/renderer/renderer_date_time_picker.cc
@@ -6,6 +6,7 @@
#include "base/strings/string_util.h"
#include "content/common/view_messages.h"
+#include "content/renderer/date_time_suggestion_builder.h"
#include "content/renderer/render_view_impl.h"
#include "third_party/WebKit/public/web/WebDateTimeChooserCompletion.h"
#include "third_party/WebKit/public/web/WebDateTimeChooserParams.h"
@@ -61,6 +62,10 @@ bool RendererDateTimePicker::Open() {
message.minimum = chooser_params_.minimum;
message.maximum = chooser_params_.maximum;
message.step = chooser_params_.step;
+ for (size_t i = 0; i < chooser_params_.suggestions.size(); i++) {
+ message.suggestions.push_back(
+ DateTimeSuggestionBuilder::Build(chooser_params_.suggestions[i]));
+ }
Send(new ViewHostMsg_OpenDateTimeDialog(routing_id(), message));
return true;
}
diff --git a/ui/android/java/res/layout/date_time_suggestion.xml b/ui/android/java/res/layout/date_time_suggestion.xml
new file mode 100644
index 0000000..e47ac76
--- /dev/null
+++ b/ui/android/java/res/layout/date_time_suggestion.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2013 The Chromium Authors. All rights reserved.
+
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/date_time_suggestion"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="44dp"
+ android:orientation="horizontal"
+ android:gravity="center_vertical">
+ <TextView
+ android:id="@+id/date_time_suggestion_value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="10dp"
+ android:layout_marginEnd="10dp"
+ android:ellipsize="end"
+ android:singleLine="true"
+ android:textSize="18sp" />
+ <TextView
+ android:id="@+id/date_time_suggestion_label"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="10dp"
+ android:layout_weight="1"
+ android:textSize="18sp"
+ android:gravity="end"
+ android:textColor="#8b8b8b"
+ android:ellipsize="end"
+ android:singleLine="true" />
+</LinearLayout>