OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / packages / inputmethods / OpenWnn / src / jp / co / omronsoft / openwnn / JAJP / TutorialJAJP.java
1 /*
2  * Copyright (C) 2008,2009  OMRON SOFTWARE Co., Ltd.
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
17 /*
18  * Copyright (C) 2008-2009 Google Inc.
19  * 
20  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
21  * use this file except in compliance with the License. You may obtain a copy of
22  * the License at
23  * 
24  * http://www.apache.org/licenses/LICENSE-2.0
25  * 
26  * Unless required by applicable law or agreed to in writing, software
27  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29  * License for the specific language governing permissions and limitations under
30  * the License.
31  */
32
33 package jp.co.omronsoft.openwnn.JAJP;
34
35 import jp.co.omronsoft.openwnn.*;
36 import android.content.Context;
37 import android.content.res.Resources;
38 import android.graphics.drawable.Drawable;
39 import android.os.Handler;
40 import android.os.Message;
41 import android.text.Layout;
42 import android.text.SpannableStringBuilder;
43 import android.text.StaticLayout;
44 import android.text.Spanned;
45 import android.text.style.ImageSpan;
46 import android.text.style.DynamicDrawableSpan;
47 import android.view.Gravity;
48 import android.view.LayoutInflater;
49 import android.view.MotionEvent;
50 import android.view.View;
51 import android.view.View.OnTouchListener;
52 import android.widget.PopupWindow;
53 import android.widget.TextView;
54
55 import java.util.ArrayList;
56 import java.util.List;
57
58 public class TutorialJAJP implements OnTouchListener {
59     
60     private List<Bubble> mBubbles = new ArrayList<Bubble>();
61     private static final int LONG_PRESS_INDEX = 8;
62     private View mInputView;
63     private OpenWnnJAJP mIme;
64     private int[] mLocation = new int[2];
65     private static final int MSG_SHOW_BUBBLE = 0;
66     
67     private int mBubbleIndex;
68     private DefaultSoftKeyboardJAJP mInputManager;
69     private boolean mEnableKeyTouch = false;
70     
71     Handler mHandler = new Handler() {
72         @Override
73         public void handleMessage(Message msg) {
74             switch (msg.what) {
75                 case MSG_SHOW_BUBBLE:
76                     Bubble bubba = (Bubble) msg.obj;
77                     bubba.show(mLocation[0], mLocation[1]);
78                     break;
79             }
80         }
81     };
82
83     class Bubble {
84         Drawable bubbleBackground;
85         int x;
86         int y;
87         int width;
88         int gravity;
89         CharSequence text;
90         boolean dismissOnTouch;
91         boolean dismissOnClose;
92         PopupWindow window;
93         TextView textView;
94         View inputView;
95
96         Bubble(Context context, View inputView,
97                 int backgroundResource, int bx, int by, int description, int guide) {
98
99             CharSequence text = context.getResources().getText(description);
100             init(context, inputView, backgroundResource, bx, by, text, guide, false);
101         }
102
103         Bubble(Context context, View inputView, int backgroundResource, int bx, int by,
104                CharSequence description, int guide, boolean leftAlign) {
105             init(context, inputView, backgroundResource, bx, by, description, guide, leftAlign);
106         }
107         
108         void init(Context context, View inputView, int backgroundResource,
109                   int bx, int by, CharSequence description, int guide, boolean leftAlign) {
110             bubbleBackground = context.getResources().getDrawable(backgroundResource);
111             x = bx;
112             y = by;
113             width = (int) (inputView.getWidth() * 0.9);
114             this.gravity = Gravity.TOP | Gravity.LEFT;
115             text = new SpannableStringBuilder()
116                 .append(description)
117                 .append("\n") 
118                 .append(context.getResources().getText(guide));
119             this.dismissOnTouch = true;
120             this.dismissOnClose = false;
121             this.inputView = inputView;
122             window = new PopupWindow(context);
123             window.setBackgroundDrawable(null);
124             LayoutInflater inflate =
125                 (LayoutInflater) context
126                         .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
127             textView = (TextView) inflate.inflate(R.layout.bubble_text, null);
128             textView.setBackgroundDrawable(bubbleBackground);
129             textView.setText(text);
130             if (leftAlign) {
131                 textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
132             }
133             window.setContentView(textView);
134             window.setFocusable(false);
135             window.setTouchable(true);
136             window.setOutsideTouchable(false);
137         }
138
139         private int chooseSize(PopupWindow pop, View parentView, CharSequence text, TextView tv) {
140             int wid = tv.getPaddingLeft() + tv.getPaddingRight();
141             int ht = tv.getPaddingTop() + tv.getPaddingBottom();
142
143             /*
144              * Figure out how big the text would be if we laid it out to the
145              * full width of this view minus the border.
146              */
147             int cap = width - wid;
148
149             Layout l = new StaticLayout(text, tv.getPaint(), cap,
150                                         Layout.Alignment.ALIGN_NORMAL, 1, 0, true);
151             float max = 0;
152             for (int i = 0; i < l.getLineCount(); i++) {
153                 max = Math.max(max, l.getLineWidth(i));
154             }
155
156             /*
157              * Now set the popup size to be big enough for the text plus the border.
158              */
159             pop.setWidth(width);
160             pop.setHeight(ht + l.getHeight());
161             return l.getHeight();
162         }
163
164         void show(int offx, int offy) {
165             int textHeight = chooseSize(window, inputView, text, textView);
166             offy -= textView.getPaddingTop() + textHeight;
167             if (inputView.getVisibility() == View.VISIBLE 
168                     && inputView.getWindowVisibility() == View.VISIBLE) {
169                 try {
170                     if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) offy -= window.getHeight();
171                     if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) offx -= window.getWidth();
172                     textView.setOnTouchListener(new View.OnTouchListener() {
173                         public boolean onTouch(View view, MotionEvent me) {
174
175                             boolean ret = !mEnableKeyTouch;
176                             switch (me.getAction()) {
177                             case MotionEvent.ACTION_UP:
178                                 if (mBubbleIndex >= mBubbles.size()) {
179                                     mInputView.setOnTouchListener(null);
180                                 } else {
181                                     TutorialJAJP.this.next();
182                                 }
183                                 break;
184                             default:
185                                 break;
186                             }
187                             return ret;
188                         }
189                     });
190                     window.showAtLocation(inputView, Gravity.NO_GRAVITY, x + offx, y + offy);
191                 } catch (Exception e) {
192                 }
193             }
194         }
195         
196         void hide() {
197             if (window.isShowing()) {
198                 textView.setOnTouchListener(null);
199                 window.dismiss();
200             }
201         }
202         
203         boolean isShowing() {
204             return window.isShowing();
205         }
206     }
207
208     /** Constructor */
209     public TutorialJAJP(OpenWnnJAJP ime, View inputView, DefaultSoftKeyboardJAJP inputManager) {
210         mInputManager = inputManager;
211         mInputView = inputView;
212         mIme = ime;
213
214         Context context = inputView.getContext();
215         int inputWidth = inputView.getWidth();
216         Resources r = inputView.getContext().getResources();
217         final int x = inputWidth / 20;
218         r.getDimensionPixelOffset(R.dimen.bubble_pointer_offset);
219
220         SpannableStringBuilder spannable = new SpannableStringBuilder();
221         Bubble button;
222
223         spannable.clear();
224         spannable.append(r.getText(R.string.tip_to_step1));
225
226         setSpan(spannable, "\u25cb", R.drawable.tutorial_12key_key);
227         button = new Bubble(context, inputView, 
228                 R.drawable.dialog_bubble, x, 0, 
229                 spannable, R.string.touch_to_continue, false);
230         mBubbles.add(button);
231
232         spannable.clear();
233         spannable.append(r.getText(R.string.tip_to_step2_a));
234
235         setSpan(spannable, "\u25cb", R.drawable.tutorial_12key_toggle);
236         button = new Bubble(context, inputView, 
237                 R.drawable.dialog_bubble, x, 0, 
238                 spannable, R.string.touch_to_continue, true);
239         mBubbles.add(button);
240
241         spannable.append(r.getText(R.string.tip_to_step2_b));
242
243         setSpan(spannable, "\u2192", R.drawable.tutorial_12key_right);
244
245         button = new Bubble(context, inputView, 
246                 R.drawable.dialog_bubble, x, 0, 
247                 spannable, R.string.touch_to_continue, true);
248         mBubbles.add(button);
249
250         spannable.append(r.getText(R.string.tip_to_step2_c));
251
252         setSpan(spannable, "\u25cb", R.drawable.tutorial_12key_toggle);
253
254         button = new Bubble(context, inputView, 
255                 R.drawable.dialog_bubble, x, 0, 
256                 spannable, R.string.touch_to_continue, true);
257         mBubbles.add(button);
258
259         spannable.append(r.getText(R.string.tip_to_step2_d));
260
261         setSpan(spannable, "\u25a0", R.drawable.tutorial_12key_space_jp);
262
263         setSpan(spannable, "\u2193", R.drawable.tutorial_12key_enter);
264
265         button = new Bubble(context, inputView, 
266                 R.drawable.dialog_bubble, x, 0, 
267                 spannable, R.string.touch_to_continue, true);
268         mBubbles.add(button);
269
270         spannable.clear();
271         spannable.append(r.getText(R.string.tip_to_step3_a));
272
273         setSpan(spannable, "\u25a0", R.drawable.tutorial_12key_mode);
274         button = new Bubble(context, inputView, 
275                 R.drawable.dialog_bubble_moji, x, 0, 
276                 spannable, R.string.touch_to_continue, false);
277         mBubbles.add(button);
278
279         button = new Bubble(context, inputView, 
280                 R.drawable.dialog_bubble_moji, x, 0, 
281                 R.string.tip_to_step3_b, R.string.touch_to_continue);
282         mBubbles.add(button);
283
284         button = new Bubble(context, inputView, 
285                 R.drawable.dialog_bubble_moji, x, 0, 
286                 R.string.tip_to_step3_c, R.string.touch_to_continue);
287         mBubbles.add(button);
288
289         spannable.clear();
290         spannable.append(r.getText(R.string.tip_to_step4));
291
292         setSpan(spannable, "\u25a0", R.drawable.tutorial_12key_mode);
293         button = new Bubble(context, inputView, 
294                 R.drawable.dialog_bubble_moji, x, 0, 
295                 spannable, R.string.touch_to_try, false);
296         mBubbles.add(button);
297
298         spannable.clear();
299         spannable.append(r.getText(R.string.tip_to_step5));
300  
301         setSpan(spannable, "\u2190", R.drawable.tutorial_back);
302  
303         button = new Bubble(context, inputView, 
304                 R.drawable.dialog_bubble, x, 0, 
305                 spannable, R.string.touch_to_continue, false);
306         mBubbles.add(button);
307
308         button = new Bubble(context, inputView, 
309                 R.drawable.dialog_bubble, x, 0, 
310                 R.string.tip_to_step6, R.string.touch_to_finish);
311         mBubbles.add(button);
312     }
313
314     private void setSpan(SpannableStringBuilder spannable, String marker, int imageResourceId) {
315         String text = spannable.toString();
316         int target = text.indexOf(marker);
317         while (0 <= target) {
318             ImageSpan span = new ImageSpan(mIme, imageResourceId,
319                     DynamicDrawableSpan.ALIGN_BOTTOM);
320             spannable.setSpan(span, target, target + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 
321             target = text.indexOf(marker, target + 1);
322         }
323     }
324     
325     public void start() {
326         mInputView.getLocationInWindow(mLocation);
327         mBubbleIndex = -1;
328         mInputView.setOnTouchListener(this);
329         next();
330     }
331
332     boolean next() {
333         if (mBubbleIndex >= 0) {
334             if (!mBubbles.get(mBubbleIndex).isShowing()) {
335                 return true;
336             }
337             for (int i = 0; i <= mBubbleIndex; i++) {
338                 mBubbles.get(i).hide();
339             }
340         }
341         mBubbleIndex++;
342         if (mBubbleIndex >= mBubbles.size()) {
343             mEnableKeyTouch = true;
344             mIme.sendDownUpKeyEvents(-1);
345             mIme.tutorialDone();
346             return false;
347         }
348
349         if ((6 <= mBubbleIndex) && (mBubbleIndex <= 8)) {
350             mInputManager.nextKeyMode();
351         }
352
353         if (mBubbleIndex == LONG_PRESS_INDEX) {
354             mEnableKeyTouch = true;
355         } else if (LONG_PRESS_INDEX < mBubbleIndex) {
356             mEnableKeyTouch = false;
357         }
358
359         mHandler.sendMessageDelayed(
360                 mHandler.obtainMessage(MSG_SHOW_BUBBLE, mBubbles.get(mBubbleIndex)), 500);
361         return true;
362     }
363     
364     void hide() {
365         for (int i = 0; i < mBubbles.size(); i++) {
366             mBubbles.get(i).hide();
367         }
368         mInputView.setOnTouchListener(null);
369     }
370
371     public boolean close() {
372         mHandler.removeMessages(MSG_SHOW_BUBBLE);
373         hide();
374         return true;
375     }
376
377     public boolean onTouch(View v, MotionEvent event) {
378         boolean ret = !mEnableKeyTouch;
379         if (event.getAction() == MotionEvent.ACTION_UP) {
380             if (mBubbleIndex >= mBubbles.size()) {
381                 mInputView.setOnTouchListener(null);
382             } else {
383                 if (mBubbleIndex != LONG_PRESS_INDEX) {
384                     next();
385                 }
386             }
387         }
388         return ret;
389     }
390 }