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 android.app.Activity;
2039b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.app.AlertDialog;
21766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.app.Dialog;
22766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.app.DialogFragment;
23766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.app.LoaderManager.LoaderCallbacks;
24766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.content.AsyncTaskLoader;
25766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.content.Context;
26766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.content.DialogInterface;
27766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.content.Intent;
28766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.content.Loader;
29813a54d216010a16d714355c61d606dd3eb589aaRoboErikimport android.hardware.input.InputDeviceIdentifier;
30766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.hardware.input.InputManager;
31766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.hardware.input.InputManager.InputDeviceListener;
3239b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.hardware.input.KeyboardLayout;
33766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.os.Bundle;
34766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.view.InputDevice;
35766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.view.LayoutInflater;
36766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.view.View;
37766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.view.ViewGroup;
38766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.widget.ArrayAdapter;
39766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.widget.CheckedTextView;
40766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.widget.RadioButton;
41766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.widget.TextView;
42766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
43265d3c2a0c36251bf8a9f571d7239b6dd404d942Tamas Berghammerimport com.android.internal.logging.nano.MetricsProto;
4439b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport com.android.settings.R;
451e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhangimport com.android.settings.core.instrumentation.InstrumentedDialogFragment;
4639b467482d1bf256a111c757e9b7621c6f523271Jason Monk
47766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport java.util.ArrayList;
48766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport java.util.Collections;
49766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
501e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhangpublic class KeyboardLayoutDialogFragment extends InstrumentedDialogFragment
51766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        implements InputDeviceListener, LoaderCallbacks<KeyboardLayoutDialogFragment.Keyboards> {
52813a54d216010a16d714355c61d606dd3eb589aaRoboErik    private static final String KEY_INPUT_DEVICE_IDENTIFIER = "inputDeviceIdentifier";
53766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
54813a54d216010a16d714355c61d606dd3eb589aaRoboErik    private InputDeviceIdentifier mInputDeviceIdentifier;
55766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private int mInputDeviceId = -1;
56766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private InputManager mIm;
57766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private KeyboardLayoutAdapter mAdapter;
5817b631988451613393c4656900c1821e23d8434aMichael Wright    private boolean mHasShownLayoutSelectionScreen;
59766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
60766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public KeyboardLayoutDialogFragment() {
61766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
62766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
63813a54d216010a16d714355c61d606dd3eb589aaRoboErik    public KeyboardLayoutDialogFragment(InputDeviceIdentifier inputDeviceIdentifier) {
64813a54d216010a16d714355c61d606dd3eb589aaRoboErik        mInputDeviceIdentifier = inputDeviceIdentifier;
65766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
66766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
671e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhang
681e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhang    @Override
691e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhang    public int getMetricsCategory() {
701e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhang        return MetricsProto.MetricsEvent.DIALOG_KEYBOARD_LAYOUT;
711e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhang    }
721e516287bd0c910f83d2ead28bf67e26dfbead86Fan Zhang
73766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
74766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onAttach(Activity activity) {
75766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onAttach(activity);
76766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
77766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        Context context = activity.getBaseContext();
78766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mIm = (InputManager)context.getSystemService(Context.INPUT_SERVICE);
79766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mAdapter = new KeyboardLayoutAdapter(context);
80766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
81766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
82766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
83766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onCreate(Bundle savedInstanceState) {
84766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onCreate(savedInstanceState);
85766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
86766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (savedInstanceState != null) {
87813a54d216010a16d714355c61d606dd3eb589aaRoboErik            mInputDeviceIdentifier = savedInstanceState.getParcelable(KEY_INPUT_DEVICE_IDENTIFIER);
88766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
89766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
90766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        getLoaderManager().initLoader(0, null, this);
91766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
92766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
93766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
94766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onSaveInstanceState(Bundle outState) {
95766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onSaveInstanceState(outState);
96813a54d216010a16d714355c61d606dd3eb589aaRoboErik        outState.putParcelable(KEY_INPUT_DEVICE_IDENTIFIER, mInputDeviceIdentifier);
97766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
98766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
99766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
100766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public Dialog onCreateDialog(Bundle savedInstanceState) {
101766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        Context context = getActivity();
102766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        LayoutInflater inflater = LayoutInflater.from(context);
103766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        AlertDialog.Builder builder = new AlertDialog.Builder(context)
104766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            .setTitle(R.string.keyboard_layout_dialog_title)
105766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            .setPositiveButton(R.string.keyboard_layout_dialog_setup_button,
106766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    new DialogInterface.OnClickListener() {
107766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        @Override
108766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        public void onClick(DialogInterface dialog, int which) {
109766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                            onSetupLayoutsButtonClicked();
110766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        }
111766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    })
112766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            .setSingleChoiceItems(mAdapter, -1,
113766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    new DialogInterface.OnClickListener() {
114766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        @Override
115766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        public void onClick(DialogInterface dialog, int which) {
116766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                            onKeyboardLayoutClicked(which);
117766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        }
118766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    })
119766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            .setView(inflater.inflate(R.layout.keyboard_layout_dialog_switch_hint, null));
120766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        updateSwitchHintVisibility();
121766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        return builder.create();
122766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
123766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
124766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
125766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onResume() {
126766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onResume();
127766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
128766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mIm.registerInputDeviceListener(this, null);
129766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
130813a54d216010a16d714355c61d606dd3eb589aaRoboErik        InputDevice inputDevice =
131813a54d216010a16d714355c61d606dd3eb589aaRoboErik                mIm.getInputDeviceByDescriptor(mInputDeviceIdentifier.getDescriptor());
132766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (inputDevice == null) {
133766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            dismiss();
134766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            return;
135766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
136766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mInputDeviceId = inputDevice.getId();
137766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
138766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
139766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
140766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onPause() {
141766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mIm.unregisterInputDeviceListener(this);
142766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mInputDeviceId = -1;
143766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
144766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onPause();
145766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
146766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
147766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
148766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onCancel(DialogInterface dialog) {
149766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onCancel(dialog);
150766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        dismiss();
151766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
152766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
153766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private void onSetupLayoutsButtonClicked() {
154766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        ((OnSetupKeyboardLayoutsListener)getTargetFragment()).onSetupKeyboardLayouts(
155813a54d216010a16d714355c61d606dd3eb589aaRoboErik                mInputDeviceIdentifier);
156766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
157766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
158766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
159766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onActivityResult(int requestCode, int resultCode, Intent data) {
160766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onActivityResult(requestCode, resultCode, data);
161766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        show(getActivity().getFragmentManager(), "layout");
162766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
163766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
164766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private void onKeyboardLayoutClicked(int which) {
165766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (which >= 0 && which < mAdapter.getCount()) {
166766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            KeyboardLayout keyboardLayout = mAdapter.getItem(which);
167766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (keyboardLayout != null) {
168813a54d216010a16d714355c61d606dd3eb589aaRoboErik                mIm.setCurrentKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
169766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        keyboardLayout.getDescriptor());
170766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
171766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            dismiss();
172766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
173766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
174766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
175766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
176766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public Loader<Keyboards> onCreateLoader(int id, Bundle args) {
177813a54d216010a16d714355c61d606dd3eb589aaRoboErik        return new KeyboardLayoutLoader(getActivity().getBaseContext(), mInputDeviceIdentifier);
178766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
179766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
180766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
181766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onLoadFinished(Loader<Keyboards> loader, Keyboards data) {
182766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mAdapter.clear();
183766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mAdapter.addAll(data.keyboardLayouts);
184766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mAdapter.setCheckedItem(data.current);
185766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        AlertDialog dialog = (AlertDialog)getDialog();
186766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (dialog != null) {
187766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            dialog.getListView().setItemChecked(data.current, true);
188766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
189766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        updateSwitchHintVisibility();
19017b631988451613393c4656900c1821e23d8434aMichael Wright        showSetupKeyboardLayoutsIfNecessary();
191766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
192766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
193766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
194766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onLoaderReset(Loader<Keyboards> loader) {
195766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mAdapter.clear();
196766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        updateSwitchHintVisibility();
197766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
198766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
199766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
200766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onInputDeviceAdded(int deviceId) {
201766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
202766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
203766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
204766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onInputDeviceChanged(int deviceId) {
205766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
206766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            getLoaderManager().restartLoader(0, null, this);
207766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
208766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
209766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
210766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
211766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onInputDeviceRemoved(int deviceId) {
212766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
213766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            dismiss();
214766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
215766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
216766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
217766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private void updateSwitchHintVisibility() {
218766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        AlertDialog dialog = (AlertDialog)getDialog();
219766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (dialog != null) {
220766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            View customPanel = dialog.findViewById(com.android.internal.R.id.customPanel);
221766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            customPanel.setVisibility(mAdapter.getCount() > 1 ? View.VISIBLE : View.GONE);
222766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
223766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
224766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
22517b631988451613393c4656900c1821e23d8434aMichael Wright    private void showSetupKeyboardLayoutsIfNecessary() {
22617b631988451613393c4656900c1821e23d8434aMichael Wright        AlertDialog dialog = (AlertDialog)getDialog();
22717b631988451613393c4656900c1821e23d8434aMichael Wright        if (dialog != null
22817b631988451613393c4656900c1821e23d8434aMichael Wright                && mAdapter.getCount() == 1 && mAdapter.getItem(0) == null
22917b631988451613393c4656900c1821e23d8434aMichael Wright                && !mHasShownLayoutSelectionScreen) {
23017b631988451613393c4656900c1821e23d8434aMichael Wright            mHasShownLayoutSelectionScreen = true;
23117b631988451613393c4656900c1821e23d8434aMichael Wright            ((OnSetupKeyboardLayoutsListener)getTargetFragment()).onSetupKeyboardLayouts(
23217b631988451613393c4656900c1821e23d8434aMichael Wright                    mInputDeviceIdentifier);
23317b631988451613393c4656900c1821e23d8434aMichael Wright        }
23417b631988451613393c4656900c1821e23d8434aMichael Wright    }
23517b631988451613393c4656900c1821e23d8434aMichael Wright
236766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private static final class KeyboardLayoutAdapter extends ArrayAdapter<KeyboardLayout> {
237766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        private final LayoutInflater mInflater;
238766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        private int mCheckedItem = -1;
239766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
240766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        public KeyboardLayoutAdapter(Context context) {
241766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            super(context, com.android.internal.R.layout.simple_list_item_2_single_choice);
242766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
243766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
244766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
245766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        public void setCheckedItem(int position) {
246766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            mCheckedItem = position;
247766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
248766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
249766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        @Override
250766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        public View getView(int position, View convertView, ViewGroup parent) {
251766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            KeyboardLayout item = getItem(position);
252766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            String label, collection;
253766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (item != null) {
254766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                label = item.getLabel();
255766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                collection = item.getCollection();
256766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            } else {
257766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                label = getContext().getString(R.string.keyboard_layout_default_label);
258766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                collection = "";
259766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
260766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
261766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            boolean checked = (position == mCheckedItem);
262766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (collection.isEmpty()) {
263766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                return inflateOneLine(convertView, parent, label, checked);
264766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            } else {
265766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                return inflateTwoLine(convertView, parent, label, collection, checked);
266766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
267766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
268766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
269766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        private View inflateOneLine(View convertView, ViewGroup parent,
270766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                String label, boolean checked) {
271766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            View view = convertView;
272766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (view == null || isTwoLine(view)) {
273766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                view = mInflater.inflate(
274766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        com.android.internal.R.layout.simple_list_item_single_choice,
275766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        parent, false);
276766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                setTwoLine(view, false);
277766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
278766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            CheckedTextView headline = (CheckedTextView) view.findViewById(android.R.id.text1);
279766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            headline.setText(label);
280766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            headline.setChecked(checked);
281766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            return view;
282766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
283766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
284766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        private View inflateTwoLine(View convertView, ViewGroup parent,
285766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                String label, String collection, boolean checked) {
286766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            View view = convertView;
287766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (view == null || !isTwoLine(view)) {
288766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                view = mInflater.inflate(
289766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        com.android.internal.R.layout.simple_list_item_2_single_choice,
290766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        parent, false);
291766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                setTwoLine(view, true);
292766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
293766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            TextView headline = (TextView) view.findViewById(android.R.id.text1);
294766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            TextView subText = (TextView) view.findViewById(android.R.id.text2);
295766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            RadioButton radioButton =
296766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    (RadioButton)view.findViewById(com.android.internal.R.id.radio);
297766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            headline.setText(label);
298766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            subText.setText(collection);
299766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            radioButton.setChecked(checked);
300766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            return view;
301766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
302766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
303766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        private static boolean isTwoLine(View view) {
304766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            return view.getTag() == Boolean.TRUE;
305766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
306766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
307766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        private static void setTwoLine(View view, boolean twoLine) {
308766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            view.setTag(Boolean.valueOf(twoLine));
309766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
310766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
311766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
3125f0b59babfbfe483855b294098613f8d0fc2f9b4Abodunrinwa Toki    private static final class KeyboardLayoutLoader extends AsyncTaskLoader<Keyboards> {
313813a54d216010a16d714355c61d606dd3eb589aaRoboErik        private final InputDeviceIdentifier mInputDeviceIdentifier;
314766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
315813a54d216010a16d714355c61d606dd3eb589aaRoboErik        public KeyboardLayoutLoader(Context context, InputDeviceIdentifier inputDeviceIdentifier) {
316766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            super(context);
317813a54d216010a16d714355c61d606dd3eb589aaRoboErik            mInputDeviceIdentifier = inputDeviceIdentifier;
318766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
319766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
320766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        @Override
321766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        public Keyboards loadInBackground() {
322766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            Keyboards keyboards = new Keyboards();
323766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            InputManager im = (InputManager)getContext().getSystemService(Context.INPUT_SERVICE);
32417b631988451613393c4656900c1821e23d8434aMichael Wright            String[] keyboardLayoutDescriptors = im.getEnabledKeyboardLayoutsForInputDevice(
325813a54d216010a16d714355c61d606dd3eb589aaRoboErik                    mInputDeviceIdentifier);
326766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            for (String keyboardLayoutDescriptor : keyboardLayoutDescriptors) {
327766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                KeyboardLayout keyboardLayout = im.getKeyboardLayout(keyboardLayoutDescriptor);
328766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                if (keyboardLayout != null) {
329766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    keyboards.keyboardLayouts.add(keyboardLayout);
330766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                }
331766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
332766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            Collections.sort(keyboards.keyboardLayouts);
333766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
334766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            String currentKeyboardLayoutDescriptor =
335813a54d216010a16d714355c61d606dd3eb589aaRoboErik                    im.getCurrentKeyboardLayoutForInputDevice(mInputDeviceIdentifier);
336766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (currentKeyboardLayoutDescriptor != null) {
337766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                final int numKeyboardLayouts = keyboards.keyboardLayouts.size();
338766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                for (int i = 0; i < numKeyboardLayouts; i++) {
339766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    if (keyboards.keyboardLayouts.get(i).getDescriptor().equals(
340766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                            currentKeyboardLayoutDescriptor)) {
341766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        keyboards.current = i;
342766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                        break;
343766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    }
344766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                }
345766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
346766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
347766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (keyboards.keyboardLayouts.isEmpty()) {
348766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                keyboards.keyboardLayouts.add(null); // default layout
349766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                keyboards.current = 0;
350766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
351766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            return keyboards;
352766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
353766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
354766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        @Override
355766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        protected void onStartLoading() {
356766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            super.onStartLoading();
357766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            forceLoad();
358766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
359766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
360766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        @Override
361766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        protected void onStopLoading() {
362766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            super.onStopLoading();
363766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            cancelLoad();
364766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
365766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
366766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
367766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public static final class Keyboards {
368766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        public final ArrayList<KeyboardLayout> keyboardLayouts = new ArrayList<KeyboardLayout>();
369766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        public int current = -1;
370766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
371766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
372766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public interface OnSetupKeyboardLayoutsListener {
373813a54d216010a16d714355c61d606dd3eb589aaRoboErik        public void onSetupKeyboardLayouts(InputDeviceIdentifier mInputDeviceIdentifier);
374766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
37517b631988451613393c4656900c1821e23d8434aMichael Wright}
376