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.SettingsPreferenceFragment;
21766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
22766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.content.Context;
23813a54d216010a16d714355c61d606dd3eb589aaRoboErikimport android.hardware.input.InputDeviceIdentifier;
24766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.hardware.input.InputManager;
25766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.hardware.input.InputManager.InputDeviceListener;
26766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.hardware.input.KeyboardLayout;
27766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.os.Bundle;
28766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.preference.CheckBoxPreference;
29766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.preference.Preference;
30766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.preference.PreferenceScreen;
31766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport android.view.InputDevice;
32766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
33766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport java.util.Arrays;
34766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport java.util.HashMap;
35766b286187d02b3da6e0142376a4478072f30a16Jeff Brownimport java.util.Map;
36766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
37766b286187d02b3da6e0142376a4478072f30a16Jeff Brownpublic class KeyboardLayoutPickerFragment extends SettingsPreferenceFragment
38766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        implements InputDeviceListener {
39813a54d216010a16d714355c61d606dd3eb589aaRoboErik    private InputDeviceIdentifier mInputDeviceIdentifier;
40766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private int mInputDeviceId = -1;
41766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private InputManager mIm;
42766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private KeyboardLayout[] mKeyboardLayouts;
43766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private HashMap<CheckBoxPreference, KeyboardLayout> mPreferenceMap =
44766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            new HashMap<CheckBoxPreference, KeyboardLayout>();
45766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
46766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    /**
47766b286187d02b3da6e0142376a4478072f30a16Jeff Brown     * Intent extra: The input device descriptor of the keyboard whose keyboard
48766b286187d02b3da6e0142376a4478072f30a16Jeff Brown     * layout is to be changed.
49766b286187d02b3da6e0142376a4478072f30a16Jeff Brown     */
50813a54d216010a16d714355c61d606dd3eb589aaRoboErik    public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
51766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
52766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
53766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onCreate(Bundle icicle) {
54766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onCreate(icicle);
55766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
56813a54d216010a16d714355c61d606dd3eb589aaRoboErik        mInputDeviceIdentifier = getActivity().getIntent().getParcelableExtra(
57813a54d216010a16d714355c61d606dd3eb589aaRoboErik                EXTRA_INPUT_DEVICE_IDENTIFIER);
58813a54d216010a16d714355c61d606dd3eb589aaRoboErik        if (mInputDeviceIdentifier == null) {
59766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            getActivity().finish();
60766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
61766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
62766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mIm = (InputManager)getSystemService(Context.INPUT_SERVICE);
63766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mKeyboardLayouts = mIm.getKeyboardLayouts();
64766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        Arrays.sort(mKeyboardLayouts);
65766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        setPreferenceScreen(createPreferenceHierarchy());
66766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
67766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
68766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
69766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onResume() {
70766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onResume();
71766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
72766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mIm.registerInputDeviceListener(this, null);
73766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
74813a54d216010a16d714355c61d606dd3eb589aaRoboErik        InputDevice inputDevice =
75813a54d216010a16d714355c61d606dd3eb589aaRoboErik                mIm.getInputDeviceByDescriptor(mInputDeviceIdentifier.getDescriptor());
76766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (inputDevice == null) {
77766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            getActivity().finish();
78766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            return;
79766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
80766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mInputDeviceId = inputDevice.getId();
81766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
82766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        updateCheckedState();
83766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
84766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
85766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
86766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onPause() {
87766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mIm.unregisterInputDeviceListener(this);
88766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        mInputDeviceId = -1;
89766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
90766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        super.onPause();
91766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
92766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
93766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
94766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
95766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            Preference preference) {
96766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (preference instanceof CheckBoxPreference) {
97766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            CheckBoxPreference checkboxPref = (CheckBoxPreference)preference;
98766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            KeyboardLayout layout = mPreferenceMap.get(checkboxPref);
99766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            if (layout != null) {
100766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                boolean checked = checkboxPref.isChecked();
101766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                if (checked) {
102813a54d216010a16d714355c61d606dd3eb589aaRoboErik                    mIm.addKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
103766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                            layout.getDescriptor());
104766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                } else {
105813a54d216010a16d714355c61d606dd3eb589aaRoboErik                    mIm.removeKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
106766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                            layout.getDescriptor());
107766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                }
108766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                return true;
109766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            }
110766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
111766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        return super.onPreferenceTreeClick(preferenceScreen, preference);
112766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
113766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
114766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
115766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onInputDeviceAdded(int deviceId) {
116766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
117766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
118766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
119766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onInputDeviceChanged(int deviceId) {
120766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
121766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            updateCheckedState();
122766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
123766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
124766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
125766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    @Override
126766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    public void onInputDeviceRemoved(int deviceId) {
127766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
128766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            getActivity().finish();
129766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
130766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
131766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
132766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private PreferenceScreen createPreferenceHierarchy() {
133766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
134766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        Context context = getActivity();
135766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
136766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        for (KeyboardLayout layout : mKeyboardLayouts) {
137766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            CheckBoxPreference pref = new CheckBoxPreference(context);
138766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            pref.setTitle(layout.getLabel());
139766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            pref.setSummary(layout.getCollection());
140766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            root.addPreference(pref);
141766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            mPreferenceMap.put(pref, layout);
142766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
143766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        return root;
144766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
145766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
146766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    private void updateCheckedState() {
147766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        String[] enabledKeyboardLayouts = mIm.getKeyboardLayoutsForInputDevice(
148813a54d216010a16d714355c61d606dd3eb589aaRoboErik                mInputDeviceIdentifier);
149766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        Arrays.sort(enabledKeyboardLayouts);
150766b286187d02b3da6e0142376a4478072f30a16Jeff Brown
151766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        for (Map.Entry<CheckBoxPreference, KeyboardLayout> entry : mPreferenceMap.entrySet()) {
152766b286187d02b3da6e0142376a4478072f30a16Jeff Brown            entry.getKey().setChecked(Arrays.binarySearch(enabledKeyboardLayouts,
153766b286187d02b3da6e0142376a4478072f30a16Jeff Brown                    entry.getValue().getDescriptor()) >= 0);
154766b286187d02b3da6e0142376a4478072f30a16Jeff Brown        }
155766b286187d02b3da6e0142376a4478072f30a16Jeff Brown    }
156766b286187d02b3da6e0142376a4478072f30a16Jeff Brown}
157