10cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard/** 20cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * Copyright (C) 2011 The Android Open Source Project 30cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * 40cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * Licensed under the Apache License, Version 2.0 (the "License"); you may not 50cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * use this file except in compliance with the License. You may obtain a copy 60cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * of the License at 70cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * 80cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * http://www.apache.org/licenses/LICENSE-2.0 90cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * 100cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * Unless required by applicable law or agreed to in writing, software 110cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 120cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 130cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * License for the specific language governing permissions and limitations 140cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * under the License. 150cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard */ 160cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 170cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardpackage com.android.inputmethod.dictionarypack; 180cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 190cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport android.content.Context; 200cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport android.content.SharedPreferences; 2141f505dc3e6ba7aa850e0c4dbe2d6093ddd6fc2dJean Chalardimport android.preference.Preference; 220cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport android.util.Log; 230cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport android.view.View; 240cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport android.view.ViewGroup; 25f8014eea341040f8d155e071e4e0c915a7ebd61dJean Chalardimport android.view.ViewParent; 26f8014eea341040f8d155e071e4e0c915a7ebd61dJean Chalardimport android.widget.ListView; 27ab0c66b9d1f732a0dc372abd6d113d2cac33b8acJean Chalardimport android.widget.TextView; 280cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 290cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport com.android.inputmethod.latin.R; 300cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 310cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport java.util.Locale; 320cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 330cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard/** 340cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * A preference for one word list. 350cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * 360cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * This preference refers to a single word list, as available in the dictionary 370cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * pack. Upon being pressed, it displays a menu to allow the user to install, disable, 380cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * enable or delete it as appropriate for the current state of the word list. 390cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard */ 4041f505dc3e6ba7aa850e0c4dbe2d6093ddd6fc2dJean Chalardpublic final class WordListPreference extends Preference { 415f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka private static final String TAG = WordListPreference.class.getSimpleName(); 420cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 430cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // What to display in the "status" field when we receive unknown data as a status from 440cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // the content provider. Empty string sounds sensible. 455f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka private static final String NO_STATUS_MESSAGE = ""; 460cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 470cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard /// Actions 485f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka private static final int ACTION_UNKNOWN = 0; 495f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka private static final int ACTION_ENABLE_DICT = 1; 505f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka private static final int ACTION_DISABLE_DICT = 2; 515f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka private static final int ACTION_DELETE_DICT = 3; 520cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 530cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // Members 540cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // The metadata word list id and version of this word list. 550cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard public final String mWordlistId; 560cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard public final int mVersion; 57a2ec5e8338c82f1e49c3d98f502dcc30c9c12fb0Jean Chalard public final Locale mLocale; 58a2ec5e8338c82f1e49c3d98f502dcc30c9c12fb0Jean Chalard public final String mDescription; 595f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka 605f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka // The id of the client for which this preference is. 615f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka private final String mClientId; 620cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // The status 6326f489493eb3a1ccb9cb0ab55627bee4c74a6fd2Jean Chalard private int mStatus; 64ab0c66b9d1f732a0dc372abd6d113d2cac33b8acJean Chalard // The size of the dictionary file 65ab0c66b9d1f732a0dc372abd6d113d2cac33b8acJean Chalard private final int mFilesize; 660cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 67c017f18a59a6b0ba1905a67193057b5b70410e06Jean Chalard private final DictionaryListInterfaceState mInterfaceState; 680cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 69c017f18a59a6b0ba1905a67193057b5b70410e06Jean Chalard public WordListPreference(final Context context, 70c017f18a59a6b0ba1905a67193057b5b70410e06Jean Chalard final DictionaryListInterfaceState dictionaryListInterfaceState, final String clientId, 71c017f18a59a6b0ba1905a67193057b5b70410e06Jean Chalard final String wordlistId, final int version, final Locale locale, 72ab0c66b9d1f732a0dc372abd6d113d2cac33b8acJean Chalard final String description, final int status, final int filesize) { 730cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard super(context, null); 74c017f18a59a6b0ba1905a67193057b5b70410e06Jean Chalard mInterfaceState = dictionaryListInterfaceState; 750cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mClientId = clientId; 760cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mVersion = version; 770cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mWordlistId = wordlistId; 78ab0c66b9d1f732a0dc372abd6d113d2cac33b8acJean Chalard mFilesize = filesize; 79a2ec5e8338c82f1e49c3d98f502dcc30c9c12fb0Jean Chalard mLocale = locale; 80a2ec5e8338c82f1e49c3d98f502dcc30c9c12fb0Jean Chalard mDescription = description; 810cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 820cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard setLayoutResource(R.layout.dictionary_line); 830cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 840cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard setTitle(description); 850cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard setStatus(status); 860cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard setKey(wordlistId); 870cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 880cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 8926f489493eb3a1ccb9cb0ab55627bee4c74a6fd2Jean Chalard public void setStatus(final int status) { 900cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard if (status == mStatus) return; 910cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard mStatus = status; 920cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard setSummary(getSummary(status)); 930cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 940cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 95a7e3e74ddd714b7e22d5e5feb7e136dcb5dc1edaJean Chalard public boolean hasStatus(final int status) { 96a7e3e74ddd714b7e22d5e5feb7e136dcb5dc1edaJean Chalard return status == mStatus; 97a7e3e74ddd714b7e22d5e5feb7e136dcb5dc1edaJean Chalard } 98a7e3e74ddd714b7e22d5e5feb7e136dcb5dc1edaJean Chalard 992b34b4eab6b04299205f47a92311d4d00f9d805fJean Chalard @Override 1002b34b4eab6b04299205f47a92311d4d00f9d805fJean Chalard public View onCreateView(final ViewGroup parent) { 1012b34b4eab6b04299205f47a92311d4d00f9d805fJean Chalard final View orphanedView = mInterfaceState.findFirstOrphanedView(); 1022b34b4eab6b04299205f47a92311d4d00f9d805fJean Chalard if (null != orphanedView) return orphanedView; // Will be sent to onBindView 1032b34b4eab6b04299205f47a92311d4d00f9d805fJean Chalard final View newView = super.onCreateView(parent); 1042b34b4eab6b04299205f47a92311d4d00f9d805fJean Chalard return mInterfaceState.addToCacheAndReturnView(newView); 1052b34b4eab6b04299205f47a92311d4d00f9d805fJean Chalard } 1062b34b4eab6b04299205f47a92311d4d00f9d805fJean Chalard 10726f489493eb3a1ccb9cb0ab55627bee4c74a6fd2Jean Chalard public boolean hasPriorityOver(final int otherPrefStatus) { 10826f489493eb3a1ccb9cb0ab55627bee4c74a6fd2Jean Chalard // Both of these should be one of MetadataDbHelper.STATUS_* 10926f489493eb3a1ccb9cb0ab55627bee4c74a6fd2Jean Chalard return mStatus > otherPrefStatus; 11026f489493eb3a1ccb9cb0ab55627bee4c74a6fd2Jean Chalard } 11126f489493eb3a1ccb9cb0ab55627bee4c74a6fd2Jean Chalard 1120cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard private String getSummary(final int status) { 1135f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final Context context = getContext(); 1140cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard switch (status) { 1155f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka // If we are deleting the word list, for the user it's like it's already deleted. 1165f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka // It should be reinstallable. Exposing to the user the whole complexity of 1175f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka // the delayed deletion process between the dictionary pack and Android Keyboard 1185f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka // would only be confusing. 1195f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka case MetadataDbHelper.STATUS_DELETING: 1205f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka case MetadataDbHelper.STATUS_AVAILABLE: 1215f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka return context.getString(R.string.dictionary_available); 1225f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka case MetadataDbHelper.STATUS_DOWNLOADING: 1235f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka return context.getString(R.string.dictionary_downloading); 1245f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka case MetadataDbHelper.STATUS_INSTALLED: 1255f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka return context.getString(R.string.dictionary_installed); 1265f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka case MetadataDbHelper.STATUS_DISABLED: 1275f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka return context.getString(R.string.dictionary_disabled); 1285f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka default: 1295f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka return NO_STATUS_MESSAGE; 1300cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 1310cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 1320cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 1332d72590ced449e1ba0065bf63c311dae805c8290Jean Chalard // The table below needs to be kept in sync with MetadataDbHelper.STATUS_* since it uses 1342d72590ced449e1ba0065bf63c311dae805c8290Jean Chalard // the values as indices. 1350cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard private static final int sStatusActionList[][] = { 1360cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // MetadataDbHelper.STATUS_UNKNOWN 1370cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard {}, 1380cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // MetadataDbHelper.STATUS_AVAILABLE 1392d72590ced449e1ba0065bf63c311dae805c8290Jean Chalard { ButtonSwitcher.STATUS_INSTALL, ACTION_ENABLE_DICT }, 1400cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // MetadataDbHelper.STATUS_DOWNLOADING 1412d72590ced449e1ba0065bf63c311dae805c8290Jean Chalard { ButtonSwitcher.STATUS_CANCEL, ACTION_DISABLE_DICT }, 1420cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // MetadataDbHelper.STATUS_INSTALLED 1432d72590ced449e1ba0065bf63c311dae805c8290Jean Chalard { ButtonSwitcher.STATUS_DELETE, ACTION_DELETE_DICT }, 1440cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // MetadataDbHelper.STATUS_DISABLED 1452d72590ced449e1ba0065bf63c311dae805c8290Jean Chalard { ButtonSwitcher.STATUS_DELETE, ACTION_DELETE_DICT }, 1460cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // MetadataDbHelper.STATUS_DELETING 1470cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // We show 'install' because the file is supposed to be deleted. 1480cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // The user may reinstall it. 1492d72590ced449e1ba0065bf63c311dae805c8290Jean Chalard { ButtonSwitcher.STATUS_INSTALL, ACTION_ENABLE_DICT } 1500cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard }; 1510cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 1525f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka static int getButtonSwitcherStatus(final int status) { 1530cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard if (status >= sStatusActionList.length) { 1540cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard Log.e(TAG, "Unknown status " + status); 1552d72590ced449e1ba0065bf63c311dae805c8290Jean Chalard return ButtonSwitcher.STATUS_NO_BUTTON; 1560cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 1572d72590ced449e1ba0065bf63c311dae805c8290Jean Chalard return sStatusActionList[status][0]; 1580cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 1590cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 1605f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka static int getActionIdFromStatusAndMenuEntry(final int status) { 1610cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard if (status >= sStatusActionList.length) { 1620cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard Log.e(TAG, "Unknown status " + status); 1630cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard return ACTION_UNKNOWN; 1640cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 1650cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard return sStatusActionList[status][1]; 1660cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 1670cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 1680cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard private void disableDict() { 1695f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final Context context = getContext(); 1705f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context); 1710cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard CommonPreferences.disable(prefs, mWordlistId); 1725f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka UpdateHandler.markAsUnused(context, mClientId, mWordlistId, mVersion, mStatus); 1730cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard if (MetadataDbHelper.STATUS_DOWNLOADING == mStatus) { 1740cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard setStatus(MetadataDbHelper.STATUS_AVAILABLE); 1750cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } else if (MetadataDbHelper.STATUS_INSTALLED == mStatus) { 1760cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // Interface-wise, we should no longer be able to come here. However, this is still 1770cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // the right thing to do if we do come here. 1780cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard setStatus(MetadataDbHelper.STATUS_DISABLED); 1790cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } else { 1800cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard Log.e(TAG, "Unexpected state of the word list for disabling " + mStatus); 1810cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 1820cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 1835f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka 1840cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard private void enableDict() { 1855f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final Context context = getContext(); 1865f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context); 1870cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard CommonPreferences.enable(prefs, mWordlistId); 1880cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // Explicit enabling by the user : allow downloading on metered data connection. 1895f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka UpdateHandler.markAsUsed(context, mClientId, mWordlistId, mVersion, mStatus, true); 1900cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard if (MetadataDbHelper.STATUS_AVAILABLE == mStatus) { 1910cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard setStatus(MetadataDbHelper.STATUS_DOWNLOADING); 1920cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } else if (MetadataDbHelper.STATUS_DISABLED == mStatus 1930cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard || MetadataDbHelper.STATUS_DELETING == mStatus) { 1940cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // If the status is DELETING, it means Android Keyboard 1950cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // has not deleted the word list yet, so we can safely 1960cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // turn it to 'installed'. The status DISABLED is still supported internally to 1970cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // avoid breaking older installations and all but there should not be a way to 1980cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard // disable a word list through the interface any more. 1990cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard setStatus(MetadataDbHelper.STATUS_INSTALLED); 2000cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } else { 2010cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard Log.e(TAG, "Unexpected state of the word list for enabling " + mStatus); 2020cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 2030cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 2045f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka 2050cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard private void deleteDict() { 2065f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final Context context = getContext(); 2075f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context); 2080cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard CommonPreferences.disable(prefs, mWordlistId); 2090cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard setStatus(MetadataDbHelper.STATUS_DELETING); 2105f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka UpdateHandler.markAsDeleting(context, mClientId, mWordlistId, mVersion, mStatus); 2110cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 2120cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 2130cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard @Override 2140cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard protected void onBindView(final View view) { 2150cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard super.onBindView(view); 2160cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard ((ViewGroup)view).setLayoutTransition(null); 217ab0c66b9d1f732a0dc372abd6d113d2cac33b8acJean Chalard 218d282ebfb71ff5bdb855508b7b546dba786d7d85aJean Chalard final DictionaryDownloadProgressBar progressBar = 219d282ebfb71ff5bdb855508b7b546dba786d7d85aJean Chalard (DictionaryDownloadProgressBar)view.findViewById(R.id.dictionary_line_progress_bar); 220ab0c66b9d1f732a0dc372abd6d113d2cac33b8acJean Chalard final TextView status = (TextView)view.findViewById(android.R.id.summary); 221d282ebfb71ff5bdb855508b7b546dba786d7d85aJean Chalard progressBar.setIds(mClientId, mWordlistId); 222ab0c66b9d1f732a0dc372abd6d113d2cac33b8acJean Chalard progressBar.setMax(mFilesize); 223ab0c66b9d1f732a0dc372abd6d113d2cac33b8acJean Chalard final boolean showProgressBar = (MetadataDbHelper.STATUS_DOWNLOADING == mStatus); 224a7e3e74ddd714b7e22d5e5feb7e136dcb5dc1edaJean Chalard setSummary(getSummary(mStatus)); 225ab0c66b9d1f732a0dc372abd6d113d2cac33b8acJean Chalard status.setVisibility(showProgressBar ? View.INVISIBLE : View.VISIBLE); 226ab0c66b9d1f732a0dc372abd6d113d2cac33b8acJean Chalard progressBar.setVisibility(showProgressBar ? View.VISIBLE : View.INVISIBLE); 227ab0c66b9d1f732a0dc372abd6d113d2cac33b8acJean Chalard 2285f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)view.findViewById( 2295f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka R.id.wordlist_button_switcher); 2302b34b4eab6b04299205f47a92311d4d00f9d805fJean Chalard // We need to clear the state of the button switcher, because we reuse views; if we didn't 2312b34b4eab6b04299205f47a92311d4d00f9d805fJean Chalard // reset it would animate from whatever its old state was. 2326912342a48b9ebf6f4dcd714b697eadac48afbdeJean Chalard buttonSwitcher.reset(mInterfaceState); 233513c63e877320bca4860dadc88e3a14ffb861e36Jean Chalard if (mInterfaceState.isOpen(mWordlistId)) { 234513c63e877320bca4860dadc88e3a14ffb861e36Jean Chalard // The button is open. 235513c63e877320bca4860dadc88e3a14ffb861e36Jean Chalard final int previousStatus = mInterfaceState.getStatus(mWordlistId); 236513c63e877320bca4860dadc88e3a14ffb861e36Jean Chalard buttonSwitcher.setStatusAndUpdateVisuals(getButtonSwitcherStatus(previousStatus)); 237513c63e877320bca4860dadc88e3a14ffb861e36Jean Chalard if (previousStatus != mStatus) { 238513c63e877320bca4860dadc88e3a14ffb861e36Jean Chalard // We come here if the status has changed since last time. We need to animate 239513c63e877320bca4860dadc88e3a14ffb861e36Jean Chalard // the transition. 240513c63e877320bca4860dadc88e3a14ffb861e36Jean Chalard buttonSwitcher.setStatusAndUpdateVisuals(getButtonSwitcherStatus(mStatus)); 241513c63e877320bca4860dadc88e3a14ffb861e36Jean Chalard mInterfaceState.setOpen(mWordlistId, mStatus); 242513c63e877320bca4860dadc88e3a14ffb861e36Jean Chalard } 243513c63e877320bca4860dadc88e3a14ffb861e36Jean Chalard } else { 244513c63e877320bca4860dadc88e3a14ffb861e36Jean Chalard // The button is closed. 245513c63e877320bca4860dadc88e3a14ffb861e36Jean Chalard buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON); 246513c63e877320bca4860dadc88e3a14ffb861e36Jean Chalard } 2475f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka buttonSwitcher.setInternalOnClickListener(new View.OnClickListener() { 2485f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka @Override 2495f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka public void onClick(final View v) { 2505f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka onActionButtonClicked(); 2515f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka } 2525f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka }); 2535f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka view.setOnClickListener(new View.OnClickListener() { 2545f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka @Override 2555f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka public void onClick(final View v) { 2565f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka onWordListClicked(v); 2575f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka } 2585f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka }); 2590cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 2600cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard 2615f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka void onWordListClicked(final View v) { 2625f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka // Note : v is the preference view 2635f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final ViewParent parent = v.getParent(); 2645f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka // Just in case something changed in the framework, test for the concrete class 2655f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka if (!(parent instanceof ListView)) return; 2665f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final ListView listView = (ListView)parent; 2675f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final int indexToOpen; 2685f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka // Close all first, we'll open back any item that needs to be open. 2695f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final boolean wasOpen = mInterfaceState.isOpen(mWordlistId); 2705f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka mInterfaceState.closeAll(); 2715f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka if (wasOpen) { 2725f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka // This button being shown. Take note that we don't want to open any button in the 2735f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka // loop below. 2745f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka indexToOpen = -1; 2755f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka } else { 2765f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka // This button was not being shown. Open it, and remember the index of this 2775f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka // child as the one to open in the following loop. 2785f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka mInterfaceState.setOpen(mWordlistId, mStatus); 2795f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka indexToOpen = listView.indexOfChild(v); 2805f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka } 2815f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final int lastDisplayedIndex = 2825f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka listView.getLastVisiblePosition() - listView.getFirstVisiblePosition(); 2835f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka // The "lastDisplayedIndex" is actually displayed, hence the <= 2845f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka for (int i = 0; i <= lastDisplayedIndex; ++i) { 2855f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)listView.getChildAt(i) 2865f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka .findViewById(R.id.wordlist_button_switcher); 2875f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka if (i == indexToOpen) { 2885f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka buttonSwitcher.setStatusAndUpdateVisuals(getButtonSwitcherStatus(mStatus)); 289d98f406dd31c9f72ba3273b10b521a1a77136ac3Jean Chalard } else { 2905f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON); 291d98f406dd31c9f72ba3273b10b521a1a77136ac3Jean Chalard } 292f8014eea341040f8d155e071e4e0c915a7ebd61dJean Chalard } 293f8014eea341040f8d155e071e4e0c915a7ebd61dJean Chalard } 294f8014eea341040f8d155e071e4e0c915a7ebd61dJean Chalard 2955f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka void onActionButtonClicked() { 2965f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka switch (getActionIdFromStatusAndMenuEntry(mStatus)) { 2975f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka case ACTION_ENABLE_DICT: 2985f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka enableDict(); 2995f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka break; 3005f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka case ACTION_DISABLE_DICT: 3015f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka disableDict(); 3025f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka break; 3035f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka case ACTION_DELETE_DICT: 3045f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka deleteDict(); 3055f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka break; 3065f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka default: 3075f00fe09e9a611b647592188316e5999465df4d3Tadashi G. Takaoka Log.e(TAG, "Unknown menu item pressed"); 3080cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 3090cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard } 3100cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard} 311