| // Copyright 2010-2014, Google Inc. |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following disclaimer |
| // in the documentation and/or other materials provided with the |
| // distribution. |
| // * Neither the name of Google Inc. nor the names of its |
| // contributors may be used to endorse or promote products derived from |
| // this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| package org.mozc.android.inputmethod.japanese.preference; |
| |
| import org.mozc.android.inputmethod.japanese.MozcLog; |
| import org.mozc.android.inputmethod.japanese.keyboard.Keyboard.KeyboardSpecification; |
| import org.mozc.android.inputmethod.japanese.preference.ClientSidePreference.KeyboardLayout; |
| import org.mozc.android.inputmethod.japanese.resources.R; |
| import org.mozc.android.inputmethod.japanese.view.Skin; |
| import org.mozc.android.inputmethod.japanese.view.SkinType; |
| import com.google.common.base.Preconditions; |
| |
| import android.content.Context; |
| import android.content.SharedPreferences; |
| import android.content.SharedPreferences.OnSharedPreferenceChangeListener; |
| import android.content.res.Resources; |
| import android.content.res.TypedArray; |
| import android.preference.Preference; |
| import android.preference.PreferenceManager; |
| import android.text.Html; |
| import android.text.method.LinkMovementMethod; |
| import android.util.AttributeSet; |
| import android.view.LayoutInflater; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.widget.AdapterView; |
| import android.widget.AdapterView.OnItemClickListener; |
| import android.widget.AdapterView.OnItemSelectedListener; |
| import android.widget.BaseAdapter; |
| import android.widget.ImageView; |
| import android.widget.TextView; |
| |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.EnumMap; |
| import java.util.List; |
| |
| /** |
| * Preference class for KeyboardLayout. |
| * |
| */ |
| public class KeyboardLayoutPreference extends Preference { |
| |
| static class Item { |
| final KeyboardLayout keyboardLayout; |
| final KeyboardSpecification specification; |
| final int titleResId; |
| final int descriptionResId; |
| Item(KeyboardLayout keyboardLayout, KeyboardSpecification specification, |
| int titleResId, int descriptionResId) { |
| this.keyboardLayout = keyboardLayout; |
| this.specification = specification; |
| this.titleResId = titleResId; |
| this.descriptionResId = descriptionResId; |
| } |
| } |
| |
| class ImageAdapter extends BaseAdapter { |
| private final EnumMap<KeyboardLayout, KeyboardPreviewDrawable> drawableMap = |
| new EnumMap<KeyboardLayout, KeyboardPreviewDrawable>(KeyboardLayout.class); |
| |
| ImageAdapter(Resources resources) { |
| for (Item item : itemList) { |
| drawableMap.put( |
| item.keyboardLayout, |
| new KeyboardPreviewDrawable(resources, item.keyboardLayout, item.specification)); |
| } |
| } |
| |
| @Override |
| public int getCount() { |
| return itemList.size(); |
| } |
| |
| @Override |
| public Object getItem(int item) { |
| return itemList.get(item); |
| } |
| |
| @Override |
| public long getItemId(int item) { |
| return item; |
| } |
| |
| @Override |
| public View getView(int position, View convertView, ViewGroup parentView) { |
| if (convertView == null) { |
| // No cached view is available. Inflate it. |
| LayoutInflater inflater = LayoutInflater.from(getContext()); |
| convertView = inflater.inflate(R.layout.pref_keyboard_layout_item, parentView, false); |
| } |
| |
| boolean isEnabled = KeyboardLayoutPreference.this.isEnabled(); |
| |
| // Needs to set the properties to the view even if a cached view is available, |
| // because the cached view might use to be used for another item. |
| Item item = itemList.get(position); |
| ImageView imageView = |
| ImageView.class.cast(convertView.findViewById(R.id.pref_inputstyle_item_image)); |
| imageView.setImageDrawable(drawableMap.get(item.keyboardLayout)); |
| imageView.setEnabled(isEnabled); |
| |
| TextView titleView = |
| TextView.class.cast(convertView.findViewById(R.id.pref_inputstyle_item_title)); |
| titleView.setText(item.titleResId); |
| titleView.setTextColor(getContext().getResources().getColor(isEnabled |
| ? R.color.pref_inputstyle_title |
| : R.color.pref_inputstyle_title_disabled)); |
| titleView.setEnabled(parentView.isEnabled()); |
| |
| updateBackground(convertView, position, getActiveIndex()); |
| return convertView; |
| } |
| |
| void setSkin(Skin skin) { |
| Preconditions.checkNotNull(skin); |
| for (KeyboardPreviewDrawable drawable : drawableMap.values()) { |
| drawable.setSkin(skin); |
| } |
| } |
| } |
| |
| private class GalleryEventListener implements OnItemSelectedListener, OnItemClickListener { |
| @Override |
| public void onItemClick(AdapterView<?> parent, View view, int position, long id) { |
| // Update the value if necessary. |
| KeyboardLayout newValue = itemList.get(position).keyboardLayout; |
| if (callChangeListener(newValue)) { |
| setValue(newValue); |
| updateAllItemBackground(parent, getActiveIndex()); |
| } |
| } |
| |
| @Override |
| public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { |
| // Update the description. |
| TextView descriptionView = TextView.class.cast( |
| View.class.cast(parent.getParent()).findViewById(R.id.pref_inputstyle_description)); |
| if (descriptionView != null) { |
| Item item = Item.class.cast(parent.getItemAtPosition(position)); |
| descriptionView.setText(Html.fromHtml( |
| descriptionView.getContext().getResources().getString(item.descriptionResId))); |
| } |
| } |
| |
| @Override |
| public void onNothingSelected(AdapterView<?> parent) { |
| // Do nothing. |
| } |
| } |
| |
| static final List<Item> itemList = Collections.unmodifiableList(Arrays.asList( |
| new Item( |
| KeyboardLayout.TWELVE_KEYS, |
| KeyboardSpecification.TWELVE_KEY_TOGGLE_FLICK_KANA, |
| R.string.pref_keyboard_layout_title_12keys, |
| R.string.pref_keyboard_layout_description_12keys), |
| new Item( |
| KeyboardLayout.QWERTY, |
| KeyboardSpecification.QWERTY_KANA, |
| R.string.pref_keyboard_layout_title_qwerty, |
| R.string.pref_keyboard_layout_description_qwerty), |
| new Item( |
| KeyboardLayout.GODAN, |
| KeyboardSpecification.GODAN_KANA, |
| R.string.pref_keyboard_layout_title_godan, |
| R.string.pref_keyboard_layout_description_godan))); |
| |
| private final ImageAdapter imageAdapter = new ImageAdapter(getContext().getResources()); |
| private final GalleryEventListener galleryEventListener = new GalleryEventListener(); |
| private final OnSharedPreferenceChangeListener sharedPreferenceChangeListener = |
| new OnSharedPreferenceChangeListener() { |
| @Override |
| public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { |
| if (key.equals(getContext().getResources().getString(R.string.pref_skin_type_key))) { |
| updateSkin(); |
| } |
| } |
| }; |
| |
| private KeyboardLayout value = KeyboardLayout.TWELVE_KEYS; |
| |
| public KeyboardLayoutPreference(Context context) { |
| super(context); |
| } |
| |
| public KeyboardLayoutPreference(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| } |
| |
| public KeyboardLayoutPreference(Context context, AttributeSet attrs, int defStyle) { |
| super(context, attrs, defStyle); |
| } |
| |
| public void setValue(KeyboardLayout value) { |
| if (value == null) { |
| throw new NullPointerException("value must not be null."); |
| } |
| |
| if (this.value != value) { |
| this.value = value; |
| persistString(value.name()); |
| notifyChanged(); |
| } |
| } |
| |
| public KeyboardLayout getValue() { |
| return value; |
| } |
| |
| private int getActiveIndex() { |
| for (int i = 0; i < itemList.size(); ++i) { |
| if (itemList.get(i).keyboardLayout == value) { |
| return i; |
| } |
| } |
| |
| MozcLog.e("Current value is not found in the itemList: " + value); |
| return 0; |
| } |
| |
| @Override |
| protected Object onGetDefaultValue(TypedArray a, int index) { |
| return toKeyboardLayoutInternal(a.getString(index)); |
| } |
| |
| @Override |
| protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { |
| setValue(restoreValue |
| ? toKeyboardLayoutInternal(getPersistedString(null)) |
| : KeyboardLayout.class.cast(defaultValue)); |
| } |
| |
| /** |
| * Parses the name and returns the {@link KeyboardLayout} instance. |
| * If invalid name or {@code null} is given, the default value {@code TWELVE_KEYS} will |
| * be returned. |
| */ |
| private KeyboardLayout toKeyboardLayoutInternal(String keyboardLayoutName) { |
| if (keyboardLayoutName != null) { |
| try { |
| return KeyboardLayout.valueOf(keyboardLayoutName); |
| } catch (IllegalArgumentException e) { |
| MozcLog.e("Invalid keyboard layout name: " + keyboardLayoutName, e); |
| } |
| } |
| |
| // Fallback. Use TWELVE_KEYS by default. |
| return KeyboardLayout.TWELVE_KEYS; |
| } |
| |
| @Override |
| protected void onBindView(View view) { |
| super.onBindView(view); |
| |
| TextView descriptionView = |
| TextView.class.cast(view.findViewById(R.id.pref_inputstyle_description)); |
| descriptionView.setMovementMethod(LinkMovementMethod.getInstance()); |
| |
| @SuppressWarnings("deprecation") |
| android.widget.Gallery gallery = |
| android.widget.Gallery.class.cast(view.findViewById(R.id.pref_inputstyle_gallery)); |
| gallery.setAdapter(imageAdapter); |
| gallery.setOnItemSelectedListener(galleryEventListener); |
| gallery.setOnItemClickListener(galleryEventListener); |
| gallery.setSelection(getActiveIndex()); |
| |
| updateSkin(); |
| } |
| |
| private static void updateAllItemBackground(AdapterView<?> gallery, int activeIndex) { |
| for (int i = 0; i < gallery.getChildCount(); ++i) { |
| View child = gallery.getChildAt(i); |
| int position = gallery.getPositionForView(child); |
| updateBackground(child, position, activeIndex); |
| } |
| } |
| |
| @SuppressWarnings("deprecation") |
| private static void updateBackground(View view, int position, int activePosition) { |
| if (position == activePosition) { |
| view.setBackgroundResource(android.R.drawable.dialog_frame); |
| } else { |
| view.setBackgroundDrawable(null); |
| } |
| } |
| |
| @Override |
| protected void onAttachedToHierarchy(PreferenceManager preferenceManager) { |
| super.onAttachedToHierarchy(preferenceManager); |
| updateSkin(); |
| getSharedPreferences().registerOnSharedPreferenceChangeListener( |
| sharedPreferenceChangeListener); |
| } |
| |
| @Override |
| protected void onPrepareForRemoval() { |
| getSharedPreferences().unregisterOnSharedPreferenceChangeListener( |
| sharedPreferenceChangeListener); |
| super.onPrepareForRemoval(); |
| } |
| |
| void updateSkin() { |
| Resources resources = getContext().getResources(); |
| SkinType skinType = PreferenceUtil.getEnum( |
| getSharedPreferences(), |
| resources.getString(R.string.pref_skin_type_key), |
| SkinType.class, SkinType.valueOf(resources.getString(R.string.pref_skin_type_default))); |
| imageAdapter.setSkin(skinType.getSkin(resources)); |
| } |
| } |