1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings.inputmethod;
18
19import com.android.settings.R;
20import com.android.settings.SettingsPreferenceFragment;
21
22import android.content.Context;
23import android.hardware.input.InputDeviceIdentifier;
24import android.hardware.input.InputManager;
25import android.hardware.input.InputManager.InputDeviceListener;
26import android.hardware.input.KeyboardLayout;
27import android.os.Bundle;
28import android.preference.CheckBoxPreference;
29import android.preference.Preference;
30import android.preference.PreferenceScreen;
31import android.view.InputDevice;
32
33import java.util.Arrays;
34import java.util.HashMap;
35import java.util.Map;
36
37public class KeyboardLayoutPickerFragment extends SettingsPreferenceFragment
38        implements InputDeviceListener {
39    private InputDeviceIdentifier mInputDeviceIdentifier;
40    private int mInputDeviceId = -1;
41    private InputManager mIm;
42    private KeyboardLayout[] mKeyboardLayouts;
43    private HashMap<CheckBoxPreference, KeyboardLayout> mPreferenceMap =
44            new HashMap<CheckBoxPreference, KeyboardLayout>();
45
46    /**
47     * Intent extra: The input device descriptor of the keyboard whose keyboard
48     * layout is to be changed.
49     */
50    public static final String EXTRA_INPUT_DEVICE_IDENTIFIER = "input_device_identifier";
51
52    @Override
53    public void onCreate(Bundle icicle) {
54        super.onCreate(icicle);
55
56        mInputDeviceIdentifier = getActivity().getIntent().getParcelableExtra(
57                EXTRA_INPUT_DEVICE_IDENTIFIER);
58        if (mInputDeviceIdentifier == null) {
59            getActivity().finish();
60        }
61
62        mIm = (InputManager)getSystemService(Context.INPUT_SERVICE);
63        mKeyboardLayouts = mIm.getKeyboardLayouts();
64        Arrays.sort(mKeyboardLayouts);
65        setPreferenceScreen(createPreferenceHierarchy());
66    }
67
68    @Override
69    public void onResume() {
70        super.onResume();
71
72        mIm.registerInputDeviceListener(this, null);
73
74        InputDevice inputDevice =
75                mIm.getInputDeviceByDescriptor(mInputDeviceIdentifier.getDescriptor());
76        if (inputDevice == null) {
77            getActivity().finish();
78            return;
79        }
80        mInputDeviceId = inputDevice.getId();
81
82        updateCheckedState();
83    }
84
85    @Override
86    public void onPause() {
87        mIm.unregisterInputDeviceListener(this);
88        mInputDeviceId = -1;
89
90        super.onPause();
91    }
92
93    @Override
94    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
95            Preference preference) {
96        if (preference instanceof CheckBoxPreference) {
97            CheckBoxPreference checkboxPref = (CheckBoxPreference)preference;
98            KeyboardLayout layout = mPreferenceMap.get(checkboxPref);
99            if (layout != null) {
100                boolean checked = checkboxPref.isChecked();
101                if (checked) {
102                    mIm.addKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
103                            layout.getDescriptor());
104                } else {
105                    mIm.removeKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
106                            layout.getDescriptor());
107                }
108                return true;
109            }
110        }
111        return super.onPreferenceTreeClick(preferenceScreen, preference);
112    }
113
114    @Override
115    public void onInputDeviceAdded(int deviceId) {
116    }
117
118    @Override
119    public void onInputDeviceChanged(int deviceId) {
120        if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
121            updateCheckedState();
122        }
123    }
124
125    @Override
126    public void onInputDeviceRemoved(int deviceId) {
127        if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
128            getActivity().finish();
129        }
130    }
131
132    private PreferenceScreen createPreferenceHierarchy() {
133        PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
134        Context context = getActivity();
135
136        for (KeyboardLayout layout : mKeyboardLayouts) {
137            CheckBoxPreference pref = new CheckBoxPreference(context);
138            pref.setTitle(layout.getLabel());
139            pref.setSummary(layout.getCollection());
140            root.addPreference(pref);
141            mPreferenceMap.put(pref, layout);
142        }
143        return root;
144    }
145
146    private void updateCheckedState() {
147        String[] enabledKeyboardLayouts = mIm.getKeyboardLayoutsForInputDevice(
148                mInputDeviceIdentifier);
149        Arrays.sort(enabledKeyboardLayouts);
150
151        for (Map.Entry<CheckBoxPreference, KeyboardLayout> entry : mPreferenceMap.entrySet()) {
152            entry.getKey().setChecked(Arrays.binarySearch(enabledKeyboardLayouts,
153                    entry.getValue().getDescriptor()) >= 0);
154        }
155    }
156}
157