chromium/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/SectionUiUtils.java

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.payments.ui;

import android.content.Context;
import android.text.Layout;
import android.text.TextPaint;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.Nullable;

import org.chromium.chrome.R;
import org.chromium.components.autofill.EditableOption;

/**
 * Utility functions for PaymentRequestSection.
 * This class is not supposed to be instantiated.
 */
public class SectionUiUtils {
    /** Avoid instantiation by accident. */
    private SectionUiUtils() {}

    /**
     * Show the section summary in the view in a single line. This is called when there is no
     * selected item in the section.
     *
     * @param context The context.
     * @param section The section to summarize.
     * @param view    The view to display the summary.
     */
    public static void showSectionSummaryInTextViewInSingeLine(
            final Context context, final SectionInformation section, final TextView view) {
        int optionCount = section.getSize();
        if (optionCount == 0) {
            view.setText(null);
            return;
        }

        // Listen for layout event to check whether the string can be fit in a single line and
        // manually elide the string in the middle if necessary.
        if (view.getLayout() == null && optionCount > 1) {
            view.addOnLayoutChangeListener(
                    new View.OnLayoutChangeListener() {
                        @Override
                        public void onLayoutChange(
                                View v,
                                int left,
                                int top,
                                int right,
                                int bottom,
                                int oldLeft,
                                int oldTop,
                                int oldRight,
                                int oldBottom) {
                            if (section.getSelectedItem() != null) {
                                view.removeOnLayoutChangeListener(this);
                                return;
                            }

                            Layout layout = view.getLayout();
                            if (layout.getEllipsisCount(0) > 0) {
                                String summary =
                                        getSectionSummaryForPreviewInASingleLine(
                                                context, section, layout, view.getPaint());
                                view.setText(summary);
                            }
                        }
                    });
        }

        String summary =
                SectionUiUtils.getSectionSummaryForPreviewInASingleLine(
                        context, section, view.getLayout(), view.getPaint());
        view.setText(summary);
    }

    private static String getSectionSummaryForPreviewInASingleLine(
            Context context,
            SectionInformation section,
            @Nullable Layout layout,
            @Nullable TextPaint paint) {
        int optionCount = section.getSize();
        assert optionCount != 0;

        EditableOption option = section.getItem(0);
        String labelSeparator = context.getString(R.string.autofill_address_summary_separator);
        String optionSummary = option.getPreviewString(labelSeparator, -1);

        // If there is only one option in the section, return the summary of that option in a single
        // line, let the TextView automatically elide it at the end.
        int moreOptionCount = optionCount - 1;
        if (moreOptionCount == 0) return optionSummary;

        // If there are more than one options in the section, then the returned string pattern is
        // "<summary of the first option>... and N more". N+1 is the total number of options in the
        // section.
        int resId = section.getPreviewStringResourceId();
        assert resId > 0;
        String summary =
                context.getResources()
                        .getQuantityString(resId, moreOptionCount, optionSummary, moreOptionCount);
        if (paint == null || layout == null) {
            // If layout or paint is null, return the full summary string. Otherwise, check and
            // shrink "<summary of the first option>" so as to make the entire summary string fits
            // in a single line.
            return summary;
        }

        int ellipsizedWidth = layout.getEllipsizedWidth();
        // This while loop will terminate since each call of getPreviewString returns a string
        // strictly shorter than the previously returned one and the appending "... and N more" must
        // be able to fit in a single line.
        while (Layout.getDesiredWidth(summary, paint) > ellipsizedWidth) {
            optionSummary = option.getPreviewString(labelSeparator, optionSummary.length());
            summary =
                    context.getResources()
                            .getQuantityString(
                                    resId, moreOptionCount, optionSummary, moreOptionCount);
        }

        return summary;
    }
}