1/*
2 * Copyright (C) 2010 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.systemui.statusbar.tablet;
18
19import android.content.Context;
20import android.os.IBinder;
21import android.provider.Settings;
22import android.util.AttributeSet;
23import android.view.inputmethod.InputMethodInfo;
24import android.view.inputmethod.InputMethodManager;
25import android.view.inputmethod.InputMethodSubtype;
26import android.view.View;
27import android.widget.ImageView;
28
29import com.android.systemui.R;
30
31import java.util.List;
32
33public class InputMethodButton extends ImageView {
34
35    private static final String  TAG = "StatusBar/InputMethodButton";
36    private static final boolean DEBUG = false;
37
38    // These values are defined in Settings application.
39    private static final int ID_IME_BUTTON_VISIBILITY_AUTO = 0;
40    private static final int ID_IME_BUTTON_VISIBILITY_ALWAYS_SHOW = 1;
41    private static final int ID_IME_BUTTON_VISIBILITY_ALWAYS_HIDE = 2;
42
43    // other services we wish to talk to
44    private final InputMethodManager mImm;
45    private final int mId;
46    private ImageView mIcon;
47    private IBinder mToken;
48    private boolean mShowButton = false;
49    private boolean mScreenLocked = false;
50    private boolean mHardKeyboardAvailable;
51
52    // Please refer to InputMethodManagerService.TAG_TRY_SUPPRESSING_IME_SWITCHER
53    private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
54
55    public InputMethodButton(Context context, AttributeSet attrs) {
56        super(context, attrs);
57
58        // Resource Id of the input method button. This id is defined in status_bar.xml
59        mId = getId();
60        // IME hookup
61        mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
62    }
63
64    @Override
65    protected void onAttachedToWindow() {
66        mIcon = (ImageView) findViewById(mId);
67
68        refreshStatusIcon();
69    }
70
71    // Refer to InputMethodManagerService.needsToShowImeSwitchOngoingNotification()
72    private boolean needsToShowIMEButtonWhenVisibilityAuto() {
73        List<InputMethodInfo> imis = mImm.getEnabledInputMethodList();
74        final int N = imis.size();
75        if (N > 2) return true;
76        if (N < 1) return false;
77        int nonAuxCount = 0;
78        int auxCount = 0;
79        InputMethodSubtype nonAuxSubtype = null;
80        InputMethodSubtype auxSubtype = null;
81        for(int i = 0; i < N; ++i) {
82            final InputMethodInfo imi = imis.get(i);
83            final List<InputMethodSubtype> subtypes = mImm.getEnabledInputMethodSubtypeList(
84                    imi, true);
85            final int subtypeCount = subtypes.size();
86            if (subtypeCount == 0) {
87                ++nonAuxCount;
88            } else {
89                for (int j = 0; j < subtypeCount; ++j) {
90                    final InputMethodSubtype subtype = subtypes.get(j);
91                    if (!subtype.isAuxiliary()) {
92                        ++nonAuxCount;
93                        nonAuxSubtype = subtype;
94                    } else {
95                        ++auxCount;
96                        auxSubtype = subtype;
97                    }
98                }
99            }
100        }
101        if (nonAuxCount > 1 || auxCount > 1) {
102            return true;
103        } else if (nonAuxCount == 1 && auxCount == 1) {
104            if (nonAuxSubtype != null && auxSubtype != null
105                    && (nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
106                            || auxSubtype.overridesImplicitlyEnabledSubtype()
107                            || nonAuxSubtype.overridesImplicitlyEnabledSubtype())
108                    && nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
109                return false;
110            }
111            return true;
112        }
113        return false;
114    }
115
116    private boolean needsToShowIMEButton() {
117        if (!mShowButton || mScreenLocked) return false;
118
119        if (mHardKeyboardAvailable) {
120            return true;
121        }
122
123        final int visibility = loadInputMethodSelectorVisibility();
124        switch (visibility) {
125            case ID_IME_BUTTON_VISIBILITY_AUTO:
126                return needsToShowIMEButtonWhenVisibilityAuto();
127            case ID_IME_BUTTON_VISIBILITY_ALWAYS_SHOW:
128                return true;
129            case ID_IME_BUTTON_VISIBILITY_ALWAYS_HIDE:
130                return false;
131        }
132        return false;
133    }
134
135    private void refreshStatusIcon() {
136        if (mIcon == null) {
137            return;
138        }
139        if (!needsToShowIMEButton()) {
140            setVisibility(View.GONE);
141            return;
142        } else {
143            setVisibility(View.VISIBLE);
144        }
145        mIcon.setImageResource(R.drawable.ic_sysbar_ime);
146    }
147
148    private int loadInputMethodSelectorVisibility() {
149        return Settings.Secure.getInt(getContext().getContentResolver(),
150                Settings.Secure.INPUT_METHOD_SELECTOR_VISIBILITY, ID_IME_BUTTON_VISIBILITY_AUTO);
151    }
152
153    public void setIconImage(int resId) {
154        if (mIcon != null) {
155            mIcon.setImageResource(resId);
156        }
157    }
158
159    public void setImeWindowStatus(IBinder token, boolean showButton) {
160        mToken = token;
161        mShowButton = showButton;
162        refreshStatusIcon();
163    }
164
165    public void setHardKeyboardStatus(boolean available) {
166        if (mHardKeyboardAvailable != available) {
167            mHardKeyboardAvailable = available;
168            refreshStatusIcon();
169        }
170    }
171
172    public void setScreenLocked(boolean locked) {
173        mScreenLocked = locked;
174        refreshStatusIcon();
175    }
176}
177