1e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa/*
259aefa242169b7a51c2381daee58ff22fd1834ceJunichi Monma * Copyright (C) 2008-2012  OMRON SOFTWARE Co., Ltd.
3e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa *
4e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License");
5e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * you may not use this file except in compliance with the License.
6e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * You may obtain a copy of the License at
7e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa *
8e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa *      http://www.apache.org/licenses/LICENSE-2.0
9e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa *
10e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * Unless required by applicable law or agreed to in writing, software
11e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS,
12e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * See the License for the specific language governing permissions and
14e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * limitations under the License.
15e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa */
16e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
17e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa/*
18e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * Copyright (C) 2008-2009 Google Inc.
19e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa *
20e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * Licensed under the Apache License, Version 2.0 (the "License"); you may not
21e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * use this file except in compliance with the License. You may obtain a copy of
22e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * the License at
23e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa *
24e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * http://www.apache.org/licenses/LICENSE-2.0
25e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa *
26e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * Unless required by applicable law or agreed to in writing, software
27e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * License for the specific language governing permissions and limitations under
30e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa * the License.
31e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa */
32e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
33e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawapackage jp.co.omronsoft.openwnn.EN;
34e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
35e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport jp.co.omronsoft.openwnn.*;
36e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.content.Context;
37e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.content.res.Resources;
38e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.graphics.drawable.Drawable;
39e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.os.Handler;
40e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.os.Message;
41e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.text.Layout;
42e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.text.SpannableStringBuilder;
43e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.text.StaticLayout;
44e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.text.Spanned;
45e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.text.style.ImageSpan;
46e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.text.style.DynamicDrawableSpan;
47e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.view.Gravity;
48e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.view.LayoutInflater;
49e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.view.MotionEvent;
50e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.view.View;
51e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.view.View.OnTouchListener;
52e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.widget.PopupWindow;
53e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport android.widget.TextView;
54e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
55e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport java.util.ArrayList;
56e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawaimport java.util.List;
57e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
58e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawapublic class TutorialEN implements OnTouchListener {
59e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
60e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    private List<Bubble> mBubbles = new ArrayList<Bubble>();
61e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    private View mInputView;
62e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    private OpenWnnEN mIme;
63e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    private int[] mLocation = new int[2];
64e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    private static final int MSG_SHOW_BUBBLE = 0;
65e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
66e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    private int mBubbleIndex;
67e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    private boolean mEnableKeyTouch = false;
68e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
69e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    Handler mHandler = new Handler() {
70e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        @Override
71e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        public void handleMessage(Message msg) {
72e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            switch (msg.what) {
73e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                case MSG_SHOW_BUBBLE:
74e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                    Bubble bubba = (Bubble) msg.obj;
75e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                    bubba.show(mLocation[0], mLocation[1]);
76e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                    break;
77e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            }
78e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        }
79e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    };
80e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
81e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    class Bubble {
82e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        Drawable bubbleBackground;
83e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        int x;
84e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        int y;
85e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        int width;
86e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        int gravity;
87e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        CharSequence text;
88e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        boolean dismissOnTouch;
89e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        boolean dismissOnClose;
90e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        PopupWindow window;
91e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        TextView textView;
92e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        View inputView;
93e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
94e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        Bubble(Context context, View inputView,
95e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                int backgroundResource, int bx, int by, int description, int guide) {
96e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
97e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            CharSequence text = context.getResources().getText(description);
98e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            init(context, inputView, backgroundResource, bx, by, text, guide, false);
99e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        }
100e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
101e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        Bubble(Context context, View inputView, int backgroundResource, int bx, int by,
102e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa               CharSequence description, int guide, boolean leftAlign) {
103e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            init(context, inputView, backgroundResource, bx, by, description, guide, leftAlign);
104e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        }
105e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
106e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        void init(Context context, View inputView, int backgroundResource,
107e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                  int bx, int by, CharSequence description, int guide, boolean leftAlign) {
108e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            bubbleBackground = context.getResources().getDrawable(backgroundResource);
109e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            x = bx;
110e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            y = by;
111e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            width = (int) (inputView.getWidth() * 0.9);
112e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            this.gravity = Gravity.TOP | Gravity.LEFT;
113e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            text = new SpannableStringBuilder()
114e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                .append(description)
115e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                .append("\n")
116e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                .append(context.getResources().getText(guide));
117e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            this.dismissOnTouch = true;
118e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            this.dismissOnClose = false;
119e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            this.inputView = inputView;
120e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            window = new PopupWindow(context);
121e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            window.setBackgroundDrawable(null);
122e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            LayoutInflater inflate =
123e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                (LayoutInflater) context
124e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
125e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            textView = (TextView) inflate.inflate(R.layout.bubble_text, null);
126e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            textView.setBackgroundDrawable(bubbleBackground);
127e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            textView.setText(text);
128e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            if (leftAlign) {
129e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
130e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            }
131e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            window.setContentView(textView);
132e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            window.setFocusable(false);
133e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            window.setTouchable(true);
134e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            window.setOutsideTouchable(false);
135e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        }
136e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
137e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        private int chooseSize(PopupWindow pop, View parentView, CharSequence text, TextView tv) {
138e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            int wid = tv.getPaddingLeft() + tv.getPaddingRight();
139e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            int ht = tv.getPaddingTop() + tv.getPaddingBottom();
140e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
141e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            /*
142e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa             * Figure out how big the text would be if we laid it out to the
143e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa             * full width of this view minus the border.
144e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa             */
145e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            int cap = width - wid;
146e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
147e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            Layout l = new StaticLayout(text, tv.getPaint(), cap,
148e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                                        Layout.Alignment.ALIGN_NORMAL, 1, 0, true);
149e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            float max = 0;
150e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            for (int i = 0; i < l.getLineCount(); i++) {
151e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                max = Math.max(max, l.getLineWidth(i));
152e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            }
153e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
154e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            /*
155e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa             * Now set the popup size to be big enough for the text plus the border.
156e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa             */
157e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            pop.setWidth(width);
158e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            pop.setHeight(ht + l.getHeight());
159e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            return l.getHeight();
160e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        }
161e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
162e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        void show(int offx, int offy) {
163e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            int textHeight = chooseSize(window, inputView, text, textView);
164e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            offy -= textView.getPaddingTop() + textHeight;
165e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            if (inputView.getVisibility() == View.VISIBLE
166e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                    && inputView.getWindowVisibility() == View.VISIBLE) {
167e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                try {
168e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                    if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) offy -= window.getHeight();
169e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                    if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) offx -= window.getWidth();
170e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                    textView.setOnTouchListener(new View.OnTouchListener() {
171e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                        public boolean onTouch(View view, MotionEvent me) {
172e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                            boolean ret = !mEnableKeyTouch;
173e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                            switch (me.getAction()) {
174e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                            case MotionEvent.ACTION_UP:
175e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                                if (mBubbleIndex >= mBubbles.size()) {
176e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                                    mInputView.setOnTouchListener(null);
177e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                                } else {
178e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                                    TutorialEN.this.next();
179e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                                }
180e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                                break;
181e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                            default:
182e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                                break;
183e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                            }
184e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                            return ret;
185e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                        }
186e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                    });
187e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                    window.showAtLocation(inputView, Gravity.NO_GRAVITY, x + offx, y + offy);
188e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                } catch (Exception e) {
189e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                }
190e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            }
191e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        }
192e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
193e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        void hide() {
194e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            if (window.isShowing()) {
195e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                textView.setOnTouchListener(null);
196e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                window.dismiss();
197e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            }
198e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        }
199e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
200e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        boolean isShowing() {
201e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            return window.isShowing();
202e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        }
203e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    }
204e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
205e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    /** Constructor */
206e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    public TutorialEN(OpenWnnEN ime, View inputView, DefaultSoftKeyboardEN inputManager) {
207e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        mInputView = inputView;
208e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        mIme = ime;
209e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
210e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        Context context = inputView.getContext();
211e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        int inputWidth = inputView.getWidth();
212e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        Resources r = inputView.getContext().getResources();
213e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        final int x = inputWidth / 20;
214e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        r.getDimensionPixelOffset(R.dimen.bubble_pointer_offset);
215e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
216e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        SpannableStringBuilder spannable = new SpannableStringBuilder();
217e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        Bubble button;
218e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
219e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        spannable.clear();
220e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        spannable.append(r.getText(R.string.tip_en_to_open_keyboard));
221e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        button = new Bubble(context, inputView,
222e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                R.drawable.dialog_bubble, x, 0,
223e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                spannable, R.string.touch_to_continue, false);
224e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        mBubbles.add(button);
225e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
226e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        spannable.clear();
227e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        spannable.append(r.getText(R.string.tip_en_to_close_keyboard));
228e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
229e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        setSpan(spannable, "\u2190", R.drawable.tutorial_back);
230e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
231e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        button = new Bubble(context, inputView,
232e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                R.drawable.dialog_bubble, x, 0,
233e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                spannable, R.string.touch_to_continue, false);
234e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        mBubbles.add(button);
235e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
236e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        button = new Bubble(context, inputView,
237e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                R.drawable.dialog_bubble, x, 0,
238e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                R.string.tip_en_end_of_tutorial, R.string.touch_to_finish);
239e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        mBubbles.add(button);
240e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    }
241e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
242e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    private void setSpan(SpannableStringBuilder spannable, String marker, int imageResourceId) {
243e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        String text = spannable.toString();
244e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        int target = text.indexOf(marker);
245e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        while (0 <= target) {
246e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            ImageSpan span = new ImageSpan(mIme, imageResourceId,
247e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                    DynamicDrawableSpan.ALIGN_BOTTOM);
248e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            spannable.setSpan(span, target, target + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
249e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            target = text.indexOf(marker, target + 1);
250e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        }
251e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    }
252e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
253e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    public void start() {
254e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        mInputView.getLocationInWindow(mLocation);
255e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        mBubbleIndex = -1;
256e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        mInputView.setOnTouchListener(this);
257e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        next();
258e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    }
259e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
260e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    boolean next() {
261e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        if (mBubbleIndex >= 0) {
262e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            if (!mBubbles.get(mBubbleIndex).isShowing()) {
263e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                return true;
264e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            }
265e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            for (int i = 0; i <= mBubbleIndex; i++) {
266e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                mBubbles.get(i).hide();
267e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            }
268e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        }
269e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        mBubbleIndex++;
270e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        if (mBubbleIndex >= mBubbles.size()) {
271e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            mEnableKeyTouch = true;
272e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            mIme.sendDownUpKeyEvents(-1);
273e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            mIme.tutorialDone();
274e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            return false;
275e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        }
276e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
277e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        mHandler.sendMessageDelayed(
278e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                mHandler.obtainMessage(MSG_SHOW_BUBBLE, mBubbles.get(mBubbleIndex)), 500);
279e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        return true;
280e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    }
281e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
282e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    void hide() {
283e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        for (int i = 0; i < mBubbles.size(); i++) {
284e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            mBubbles.get(i).hide();
285e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        }
286e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        mInputView.setOnTouchListener(null);
287e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    }
288e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
289e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    public boolean close() {
290e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        mHandler.removeMessages(MSG_SHOW_BUBBLE);
291e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        hide();
292e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        return true;
293e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    }
294e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa
295e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    public boolean onTouch(View v, MotionEvent event) {
296e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        boolean ret = !mEnableKeyTouch;
297e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        if (event.getAction() == MotionEvent.ACTION_UP) {
298e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            if (mBubbleIndex >= mBubbles.size()) {
299e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa                mInputView.setOnTouchListener(null);
300e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa            }
301e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        }
302e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa        return ret;
303e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa    }
304e83971e4dafd53e9fb00386355afdbae7e00c0cfDaisuke Miyakawa}
305