1766b286187d02b3da6e0142376a4478072f30a16Jeff Brown/*
2766b286187d02b3da6e0142376a4478072f30a16Jeff Brown * Copyright (C) 2012 The Android Open Source Project
3766b286187d02b3da6e0142376a4478072f30a16Jeff Brown *
4766b286187d02b3da6e0142376a4478072f30a16Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
5766b286187d02b3da6e0142376a4478072f30a16Jeff Brown * you may not use this file except in compliance with the License.
6766b286187d02b3da6e0142376a4478072f30a16Jeff Brown * You may obtain a copy of the License at
7766b286187d02b3da6e0142376a4478072f30a16Jeff Brown *
8766b286187d02b3da6e0142376a4478072f30a16Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
9766b286187d02b3da6e0142376a4478072f30a16Jeff Brown *
10766b286187d02b3da6e0142376a4478072f30a16Jeff Brown * Unless required by applicable law or agreed to in writing, software
11766b286187d02b3da6e0142376a4478072f30a16Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
12766b286187d02b3da6e0142376a4478072f30a16Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13766b286187d02b3da6e0142376a4478072f30a16Jeff Brown * See the License for the specific language governing permissions and
14766b286187d02b3da6e0142376a4478072f30a16Jeff Brown * limitations under the License.
15766b286187d02b3da6e0142376a4478072f30a16Jeff Brown */
16766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
17766b286187d02b3da6e0142376a4478072f30a16Jeff Brownpackage com.android.settings.inputmethod;
18766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
19766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport com.android.settings.R;
20766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport com.android.settings.Settings.KeyboardLayoutPickerActivity;
21766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
22766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.app.AlertDialog;
23766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.app.Activity;
24766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.app.Dialog;
25766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.app.DialogFragment;
26766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.app.LoaderManager.LoaderCallbacks;
27766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.content.AsyncTaskLoader;
28766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.content.Context;
29766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.content.DialogInterface;
30766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.content.Intent;
31766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.content.Loader;
32766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.content.res.Resources;
33766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.hardware.input.InputManager;
34766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.hardware.input.KeyboardLayout;
35766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.hardware.input.InputManager.InputDeviceListener;
36766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.os.Bundle;
37766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.view.InputDevice;
38766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.view.LayoutInflater;
39766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.view.View;
40766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.view.ViewGroup;
41766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.widget.ArrayAdapter;
42766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.widget.CheckedTextView;
43766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.widget.RadioButton;
44766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.widget.TextView;
45766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
46766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport java.util.ArrayList;
47766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport java.util.Collections;
48766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
49766b286187d02b3da6e0142376a4478072f30a16Jeff Brownpublic class KeyboardLayoutDialogFragment extends DialogFragment
50766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        implements InputDeviceListener, LoaderCallbacks<KeyboardLayoutDialogFragment.Keyboards> {
51766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private static final String KEY_INPUT_DEVICE_DESCRIPTOR = "inputDeviceDescriptor";
52766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
53766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private String mInputDeviceDescriptor;
54766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private int mInputDeviceId = -1;
55766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private InputManager mIm;
56766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private KeyboardLayoutAdapter mAdapter;
57766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
58766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public KeyboardLayoutDialogFragment() {
59766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
60766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
61766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public KeyboardLayoutDialogFragment(String inputDeviceDescriptor) {
62766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mInputDeviceDescriptor = inputDeviceDescriptor;
63766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
64766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
65766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
66766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onAttach(Activity activity) {
67766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onAttach(activity);
68766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
69766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        Context context = activity.getBaseContext();
70766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mIm = (InputManager)context.getSystemService(Context.INPUT_SERVICE);
71766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mAdapter = new KeyboardLayoutAdapter(context);
72766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
73766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
74766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
75766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onCreate(Bundle savedInstanceState) {
76766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onCreate(savedInstanceState);
77766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
78766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (savedInstanceState != null) {
79766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            mInputDeviceDescriptor = savedInstanceState.getString(KEY_INPUT_DEVICE_DESCRIPTOR);
80766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
81766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
82766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        getLoaderManager().initLoader(0, null, this);
83766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
84766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
85766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
86766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onSaveInstanceState(Bundle outState) {
87766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onSaveInstanceState(outState);
88766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        outState.putString(KEY_INPUT_DEVICE_DESCRIPTOR, mInputDeviceDescriptor);
89766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
90766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
91766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
92766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public Dialog onCreateDialog(Bundle savedInstanceState) {
93766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        Context context = getActivity();
94766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        LayoutInflater inflater = LayoutInflater.from(context);
95766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        AlertDialog.Builder builder = new AlertDialog.Builder(context)
96766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            .setTitle(R.string.keyboard_layout_dialog_title)
97766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            .setPositiveButton(R.string.keyboard_layout_dialog_setup_button,
98766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    new DialogInterface.OnClickListener() {
99766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        @Override
100766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        public void onClick(DialogInterface dialog, int which) {
101766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                            onSetupLayoutsButtonClicked();
102766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        }
103766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    })
104766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            .setSingleChoiceItems(mAdapter, -1,
105766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    new DialogInterface.OnClickListener() {
106766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        @Override
107766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        public void onClick(DialogInterface dialog, int which) {
108766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                            onKeyboardLayoutClicked(which);
109766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        }
110766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    })
111766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            .setView(inflater.inflate(R.layout.keyboard_layout_dialog_switch_hint, null));
112766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        updateSwitchHintVisibility();
113766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        return builder.create();
114766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
115766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
116766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
117766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onResume() {
118766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onResume();
119766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
120766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mIm.registerInputDeviceListener(this, null);
121766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
122766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        InputDevice inputDevice = mIm.getInputDeviceByDescriptor(mInputDeviceDescriptor);
123766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (inputDevice == null) {
124766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            dismiss();
125766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            return;
126766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
127766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mInputDeviceId = inputDevice.getId();
128766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
129766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
130766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
131766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onPause() {
132766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mIm.unregisterInputDeviceListener(this);
133766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mInputDeviceId = -1;
134766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
135766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onPause();
136766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
137766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
138766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
139766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onCancel(DialogInterface dialog) {
140766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onCancel(dialog);
141766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        dismiss();
142766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
143766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
144766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private void onSetupLayoutsButtonClicked() {
145766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        ((OnSetupKeyboardLayoutsListener)getTargetFragment()).onSetupKeyboardLayouts(
146766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                mInputDeviceDescriptor);
147766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
148766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
149766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
150766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onActivityResult(int requestCode, int resultCode, Intent data) {
151766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onActivityResult(requestCode, resultCode, data);
152766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        show(getActivity().getFragmentManager(), "layout");
153766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
154766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
155766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private void onKeyboardLayoutClicked(int which) {
156766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (which >= 0 && which < mAdapter.getCount()) {
157766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            KeyboardLayout keyboardLayout = mAdapter.getItem(which);
158766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (keyboardLayout != null) {
159766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                mIm.setCurrentKeyboardLayoutForInputDevice(mInputDeviceDescriptor,
160766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        keyboardLayout.getDescriptor());
161766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
162766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            dismiss();
163766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
164766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
165766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
166766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
167766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public Loader<Keyboards> onCreateLoader(int id, Bundle args) {
168766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        return new KeyboardLayoutLoader(getActivity().getBaseContext(), mInputDeviceDescriptor);
169766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
170766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
171766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
172766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onLoadFinished(Loader<Keyboards> loader, Keyboards data) {
173766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mAdapter.clear();
174766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mAdapter.addAll(data.keyboardLayouts);
175766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mAdapter.setCheckedItem(data.current);
176766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        AlertDialog dialog = (AlertDialog)getDialog();
177766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (dialog != null) {
178766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            dialog.getListView().setItemChecked(data.current, true);
179766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
180766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        updateSwitchHintVisibility();
181766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
182766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
183766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
184766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onLoaderReset(Loader<Keyboards> loader) {
185766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mAdapter.clear();
186766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        updateSwitchHintVisibility();
187766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
188766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
189766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
190766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onInputDeviceAdded(int deviceId) {
191766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
192766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
193766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
194766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onInputDeviceChanged(int deviceId) {
195766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
196766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            getLoaderManager().restartLoader(0, null, this);
197766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
198766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
199766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
200766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
201766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onInputDeviceRemoved(int deviceId) {
202766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
203766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            dismiss();
204766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
205766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
206766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
207766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private void updateSwitchHintVisibility() {
208766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        AlertDialog dialog = (AlertDialog)getDialog();
209766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (dialog != null) {
210766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            View customPanel = dialog.findViewById(com.android.internal.R.id.customPanel);
211766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            customPanel.setVisibility(mAdapter.getCount() > 1 ? View.VISIBLE : View.GONE);
212766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
213766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
214766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
215766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private static final class KeyboardLayoutAdapter extends ArrayAdapter<KeyboardLayout> {
216766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        private final LayoutInflater mInflater;
217766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        private int mCheckedItem = -1;
218766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
219766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        public KeyboardLayoutAdapter(Context context) {
220766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            super(context, com.android.internal.R.layout.simple_list_item_2_single_choice);
221766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
222766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
223766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
224766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        public void setCheckedItem(int position) {
225766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            mCheckedItem = position;
226766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
227766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
228766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        @Override
229766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        public View getView(int position, View convertView, ViewGroup parent) {
230766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            KeyboardLayout item = getItem(position);
231766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            String label, collection;
232766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (item != null) {
233766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                label = item.getLabel();
234766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                collection = item.getCollection();
235766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            } else {
236766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                label = getContext().getString(R.string.keyboard_layout_default_label);
237766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                collection = "";
238766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
239766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
240766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            boolean checked = (position == mCheckedItem);
241766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (collection.isEmpty()) {
242766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                return inflateOneLine(convertView, parent, label, checked);
243766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            } else {
244766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                return inflateTwoLine(convertView, parent, label, collection, checked);
245766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
246766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
247766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
248766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        private View inflateOneLine(View convertView, ViewGroup parent,
249766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                String label, boolean checked) {
250766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            View view = convertView;
251766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (view == null || isTwoLine(view)) {
252766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                view = mInflater.inflate(
253766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        com.android.internal.R.layout.simple_list_item_single_choice,
254766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        parent, false);
255766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                setTwoLine(view, false);
256766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
257766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            CheckedTextView headline = (CheckedTextView) view.findViewById(android.R.id.text1);
258766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            headline.setText(label);
259766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            headline.setChecked(checked);
260766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            return view;
261766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
262766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
263766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        private View inflateTwoLine(View convertView, ViewGroup parent,
264766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                String label, String collection, boolean checked) {
265766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            View view = convertView;
266766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (view == null || !isTwoLine(view)) {
267766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                view = mInflater.inflate(
268766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        com.android.internal.R.layout.simple_list_item_2_single_choice,
269766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        parent, false);
270766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                setTwoLine(view, true);
271766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
272766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            TextView headline = (TextView) view.findViewById(android.R.id.text1);
273766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            TextView subText = (TextView) view.findViewById(android.R.id.text2);
274766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            RadioButton radioButton =
275766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    (RadioButton)view.findViewById(com.android.internal.R.id.radio);
276766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            headline.setText(label);
277766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            subText.setText(collection);
278766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            radioButton.setChecked(checked);
279766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            return view;
280766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
281766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
282766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        private static boolean isTwoLine(View view) {
283766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            return view.getTag() == Boolean.TRUE;
284766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
285766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
286766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        private static void setTwoLine(View view, boolean twoLine) {
287766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            view.setTag(Boolean.valueOf(twoLine));
288766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
289766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
290766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
291766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private static final class KeyboardLayoutLoader extends AsyncTaskLoader<Keyboards> {
292766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        private final String mInputDeviceDescriptor;
293766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
294766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        public KeyboardLayoutLoader(Context context, String inputDeviceDescriptor) {
295766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            super(context);
296766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            mInputDeviceDescriptor = inputDeviceDescriptor;
297766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
298766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
299766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        @Override
300766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        public Keyboards loadInBackground() {
301766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            Keyboards keyboards = new Keyboards();
302766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            InputManager im = (InputManager)getContext().getSystemService(Context.INPUT_SERVICE);
303766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            String[] keyboardLayoutDescriptors = im.getKeyboardLayoutsForInputDevice(
304766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    mInputDeviceDescriptor);
305766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            for (String keyboardLayoutDescriptor : keyboardLayoutDescriptors) {
306766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                KeyboardLayout keyboardLayout = im.getKeyboardLayout(keyboardLayoutDescriptor);
307766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                if (keyboardLayout != null) {
308766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    keyboards.keyboardLayouts.add(keyboardLayout);
309766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                }
310766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
311766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            Collections.sort(keyboards.keyboardLayouts);
312766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
313766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            String currentKeyboardLayoutDescriptor =
314766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    im.getCurrentKeyboardLayoutForInputDevice(mInputDeviceDescriptor);
315766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (currentKeyboardLayoutDescriptor != null) {
316766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                final int numKeyboardLayouts = keyboards.keyboardLayouts.size();
317766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                for (int i = 0; i < numKeyboardLayouts; i++) {
318766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    if (keyboards.keyboardLayouts.get(i).getDescriptor().equals(
319766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                            currentKeyboardLayoutDescriptor)) {
320766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        keyboards.current = i;
321766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        break;
322766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    }
323766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                }
324766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
325766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
326766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (keyboards.keyboardLayouts.isEmpty()) {
327766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                keyboards.keyboardLayouts.add(null); // default layout
328766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                keyboards.current = 0;
329766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
330766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            return keyboards;
331766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
332766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
333766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        @Override
334766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        protected void onStartLoading() {
335766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            super.onStartLoading();
336766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            forceLoad();
337766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
338766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
339766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        @Override
340766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        protected void onStopLoading() {
341766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            super.onStopLoading();
342766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            cancelLoad();
343766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
344766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
345766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
346766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public static final class Keyboards {
347766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        public final ArrayList<KeyboardLayout> keyboardLayouts = new ArrayList<KeyboardLayout>();
348766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        public int current = -1;
349766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
350766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
351766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public interface OnSetupKeyboardLayoutsListener {
352766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        public void onSetupKeyboardLayouts(String inputDeviceDescriptor);
353766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
354766b286187d02b3da6e0142376a4478072f30a16Jeff Brown}