1/*
2 * Copyright (C) 2014 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.inputmethod.keyboard.emoji;
18
19import android.support.v4.view.PagerAdapter;
20import android.util.Log;
21import android.util.SparseArray;
22import android.view.LayoutInflater;
23import android.view.View;
24import android.view.ViewGroup;
25
26import com.android.inputmethod.keyboard.Key;
27import com.android.inputmethod.keyboard.Keyboard;
28import com.android.inputmethod.keyboard.KeyboardView;
29import com.android.inputmethod.latin.R;
30
31final class EmojiPalettesAdapter extends PagerAdapter {
32    private static final String TAG = EmojiPalettesAdapter.class.getSimpleName();
33    private static final boolean DEBUG_PAGER = false;
34
35    private final EmojiPageKeyboardView.OnKeyEventListener mListener;
36    private final DynamicGridKeyboard mRecentsKeyboard;
37    private final SparseArray<EmojiPageKeyboardView> mActiveKeyboardViews = new SparseArray<>();
38    private final EmojiCategory mEmojiCategory;
39    private int mActivePosition = 0;
40
41    public EmojiPalettesAdapter(final EmojiCategory emojiCategory,
42            final EmojiPageKeyboardView.OnKeyEventListener listener) {
43        mEmojiCategory = emojiCategory;
44        mListener = listener;
45        mRecentsKeyboard = mEmojiCategory.getKeyboard(EmojiCategory.ID_RECENTS, 0);
46    }
47
48    public void flushPendingRecentKeys() {
49        mRecentsKeyboard.flushPendingRecentKeys();
50        final KeyboardView recentKeyboardView =
51                mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
52        if (recentKeyboardView != null) {
53            recentKeyboardView.invalidateAllKeys();
54        }
55    }
56
57    public void addRecentKey(final Key key) {
58        if (mEmojiCategory.isInRecentTab()) {
59            mRecentsKeyboard.addPendingKey(key);
60            return;
61        }
62        mRecentsKeyboard.addKeyFirst(key);
63        final KeyboardView recentKeyboardView =
64                mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
65        if (recentKeyboardView != null) {
66            recentKeyboardView.invalidateAllKeys();
67        }
68    }
69
70    public void onPageScrolled() {
71        releaseCurrentKey(false /* withKeyRegistering */);
72    }
73
74    public void releaseCurrentKey(final boolean withKeyRegistering) {
75        // Make sure the delayed key-down event (highlight effect and haptic feedback) will be
76        // canceled.
77        final EmojiPageKeyboardView currentKeyboardView =
78                mActiveKeyboardViews.get(mActivePosition);
79        if (currentKeyboardView == null) {
80            return;
81        }
82        currentKeyboardView.releaseCurrentKey(withKeyRegistering);
83    }
84
85    @Override
86    public int getCount() {
87        return mEmojiCategory.getTotalPageCountOfAllCategories();
88    }
89
90    @Override
91    public void setPrimaryItem(final ViewGroup container, final int position,
92            final Object object) {
93        if (mActivePosition == position) {
94            return;
95        }
96        final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition);
97        if (oldKeyboardView != null) {
98            oldKeyboardView.releaseCurrentKey(false /* withKeyRegistering */);
99            oldKeyboardView.deallocateMemory();
100        }
101        mActivePosition = position;
102    }
103
104    @Override
105    public Object instantiateItem(final ViewGroup container, final int position) {
106        if (DEBUG_PAGER) {
107            Log.d(TAG, "instantiate item: " + position);
108        }
109        final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position);
110        if (oldKeyboardView != null) {
111            oldKeyboardView.deallocateMemory();
112            // This may be redundant but wanted to be safer..
113            mActiveKeyboardViews.remove(position);
114        }
115        final Keyboard keyboard =
116                mEmojiCategory.getKeyboardFromPagePosition(position);
117        final LayoutInflater inflater = LayoutInflater.from(container.getContext());
118        final EmojiPageKeyboardView keyboardView = (EmojiPageKeyboardView)inflater.inflate(
119                R.layout.emoji_keyboard_page, container, false /* attachToRoot */);
120        keyboardView.setKeyboard(keyboard);
121        keyboardView.setOnKeyEventListener(mListener);
122        container.addView(keyboardView);
123        mActiveKeyboardViews.put(position, keyboardView);
124        return keyboardView;
125    }
126
127    @Override
128    public boolean isViewFromObject(final View view, final Object object) {
129        return view == object;
130    }
131
132    @Override
133    public void destroyItem(final ViewGroup container, final int position,
134            final Object object) {
135        if (DEBUG_PAGER) {
136            Log.d(TAG, "destroy item: " + position + ", " + object.getClass().getSimpleName());
137        }
138        final EmojiPageKeyboardView keyboardView = mActiveKeyboardViews.get(position);
139        if (keyboardView != null) {
140            keyboardView.deallocateMemory();
141            mActiveKeyboardViews.remove(position);
142        }
143        if (object instanceof View) {
144            container.removeView((View)object);
145        } else {
146            Log.w(TAG, "Warning!!! Emoji palette may be leaking. " + object);
147        }
148    }
149}
150