// 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.chrome.browser.infobar; import android.content.Context; import android.view.View; import android.widget.AdapterView; import android.widget.Spinner; import org.chromium.chrome.R; import org.chromium.chrome.browser.infobar.InfoBarControlLayout.InfoBarArrayAdapter; import java.util.ArrayList; /** * Language panel shown in the translate infobar. */ public class TranslateLanguagePanel implements TranslateSubPanel, AdapterView.OnItemSelectedListener { private static final int LANGUAGE_TYPE_SOURCE = 0; private static final int LANGUAGE_TYPE_TARGET = 1; // UI elements. private Spinner mSourceSpinner; private Spinner mTargetSpinner; // Items that are not interacted with. // Provided by the caller, the new languages will be set here if the user // clicks "done". private final TranslateOptions mOptions; // This object will be used to keep the state for the time the // panel is opened it can be totally discarded in the end if the user // clicks "cancel". private final TranslateOptions mSessionOptions; private InfoBarArrayAdapter<SpinnerLanguageElement> mSourceAdapter; private InfoBarArrayAdapter<SpinnerLanguageElement> mTargetAdapter; private final SubPanelListener mListener; /** * Display language drop downs so they can be picked as source or * target for a translation. * * @param listener triggered when the panel is closed * @param options will be modified with the new languages selected. */ public TranslateLanguagePanel(SubPanelListener listener, TranslateOptions options) { mListener = listener; mOptions = options; mSessionOptions = new TranslateOptions(mOptions); } @Override public void createContent(Context context, InfoBarLayout layout) { mSourceSpinner = null; mTargetSpinner = null; String changeLanguage = context.getString(R.string.translate_infobar_change_languages); layout.setMessage(changeLanguage); setUpSpinners(context, layout); // Set up the buttons. layout.setButtons(context.getString(R.string.translate_button_done), context.getString(R.string.cancel)); } @Override public void onButtonClicked(boolean primary) { if (primary) { mOptions.setSourceLanguage(mSessionOptions.sourceLanguageCode()); mOptions.setTargetLanguage(mSessionOptions.targetLanguageCode()); } mListener.onPanelClosed(ActionType.NONE); } private void setUpSpinners(Context context, InfoBarLayout layout) { // Set up the spinners. InfoBarControlLayout controlLayout = layout.addControlLayout(); mSourceAdapter = new InfoBarArrayAdapter<SpinnerLanguageElement>( context, context.getString(R.string.translate_options_source_hint)); mTargetAdapter = new InfoBarArrayAdapter<SpinnerLanguageElement>( context, context.getString(R.string.translate_options_target_hint)); mSourceSpinner = controlLayout.addSpinner(R.id.translate_infobar_source_spinner, mSourceAdapter); mTargetSpinner = controlLayout.addSpinner(R.id.translate_infobar_target_spinner, mTargetAdapter); mSourceSpinner.setOnItemSelectedListener(this); mTargetSpinner.setOnItemSelectedListener(this); reloadSpinners(); // Compute the minimum value width for one Spinner and use it for the other. mTargetAdapter.setMinWidthRequiredForValues( mSourceAdapter.computeMinWidthRequiredForValues()); } private void reloadSpinners() { mSourceAdapter.clear(); mTargetAdapter.clear(); mSourceAdapter.addAll(createSpinnerLanguages(mSessionOptions.targetLanguageCode())); mTargetAdapter.addAll(createSpinnerLanguages(mSessionOptions.sourceLanguageCode())); int originalSourceSelection = mSourceSpinner.getSelectedItemPosition(); int newSourceSelection = getSelectionPosition(LANGUAGE_TYPE_SOURCE); if (originalSourceSelection != newSourceSelection) { mSourceSpinner.setSelection(newSourceSelection); } int originalTargetSelection = mTargetSpinner.getSelectedItemPosition(); int newTargetSelection = getSelectionPosition(LANGUAGE_TYPE_TARGET); if (originalTargetSelection != newTargetSelection) { mTargetSpinner.setSelection(newTargetSelection); } } private int getSelectionPosition(int languageType) { String position_code = languageType == LANGUAGE_TYPE_SOURCE ? mSessionOptions.sourceLanguageCode() : mSessionOptions.targetLanguageCode(); // Since the source and target languages cannot appear in both spinners, // the index for the source language can be off by one if comes after the // target language alphabetically (and vice versa). String opposite_code = languageType == LANGUAGE_TYPE_SOURCE ? mSessionOptions.targetLanguageCode() : mSessionOptions.sourceLanguageCode(); int position = -1; int opposite = -1; for (int i = 0; i < mSessionOptions.allLanguages().size(); ++i) { if (mSessionOptions.allLanguages().get(i).mLanguageCode.equals(position_code)) { position = i; } if (mSessionOptions.allLanguages().get(i).mLanguageCode.equals(opposite_code)) { opposite = i; } if (opposite > -1 && position > -1) break; } if (opposite < position) position -= 1; return position; } @Override public void onItemSelected(AdapterView<?> adapter, View view, int position, long id) { Spinner spinner = (Spinner) adapter; String newCode = ((SpinnerLanguageElement) spinner.getSelectedItem()).getLanguageCode(); if (spinner == mSourceSpinner && !newCode.equals(mSessionOptions.sourceLanguageCode())) { mSessionOptions.setSourceLanguage(newCode); reloadSpinners(); } if (spinner == mTargetSpinner && !newCode.equals(mSessionOptions.targetLanguageCode())) { mSessionOptions.setTargetLanguage(newCode); reloadSpinners(); } } @Override public void onNothingSelected(AdapterView<?> adapter) { } /** * Determines what languages will be shown in the Spinner. * @param avoidCode ISO code of the language to avoid displaying. * Use "" to display all languages. */ private ArrayList<SpinnerLanguageElement> createSpinnerLanguages(String avoidCode) { ArrayList<SpinnerLanguageElement> result = new ArrayList<SpinnerLanguageElement>(); for (TranslateOptions.TranslateLanguagePair language : mSessionOptions.allLanguages()) { if (!language.mLanguageCode.equals(avoidCode)) { result.add(new SpinnerLanguageElement( language.mLanguageRepresentation, language.mLanguageCode)); } } return result; } /** * The element that goes inside the spinner. */ private static class SpinnerLanguageElement { private final String mLanguageName; private final String mLanguageCode; public SpinnerLanguageElement(String languageName, String languageCode) { mLanguageName = languageName; mLanguageCode = languageCode; } public String getLanguageCode() { return mLanguageCode; } /** * This is the text displayed in the spinner element so make sure no debug information * is added. */ @Override public String toString() { return mLanguageName; } } }