/* * Copyright (C) 2008-2012 OMRON SOFTWARE Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Copyright (C) 2008-2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package jp.co.omronsoft.openwnn.JAJP; import jp.co.omronsoft.openwnn.*; import android.content.Context; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Message; import android.text.Layout; import android.text.SpannableStringBuilder; import android.text.StaticLayout; import android.text.Spanned; import android.text.style.ImageSpan; import android.text.style.DynamicDrawableSpan; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.PopupWindow; import android.widget.TextView; import java.util.ArrayList; import java.util.List; public class TutorialJAJP implements OnTouchListener { private List mBubbles = new ArrayList(); private static final int LONG_PRESS_INDEX = 8; private View mInputView; private OpenWnnJAJP mIme; private int[] mLocation = new int[2]; private static final int MSG_SHOW_BUBBLE = 0; private int mBubbleIndex; private DefaultSoftKeyboardJAJP mInputManager; private boolean mEnableKeyTouch = false; Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SHOW_BUBBLE: Bubble bubba = (Bubble) msg.obj; bubba.show(mLocation[0], mLocation[1]); break; } } }; class Bubble { Drawable bubbleBackground; int x; int y; int width; int gravity; CharSequence text; boolean dismissOnTouch; boolean dismissOnClose; PopupWindow window; TextView textView; View inputView; Bubble(Context context, View inputView, int backgroundResource, int bx, int by, int description, int guide) { CharSequence text = context.getResources().getText(description); init(context, inputView, backgroundResource, bx, by, text, guide, false); } Bubble(Context context, View inputView, int backgroundResource, int bx, int by, CharSequence description, int guide, boolean leftAlign) { init(context, inputView, backgroundResource, bx, by, description, guide, leftAlign); } void init(Context context, View inputView, int backgroundResource, int bx, int by, CharSequence description, int guide, boolean leftAlign) { bubbleBackground = context.getResources().getDrawable(backgroundResource); x = bx; y = by; width = (int) (inputView.getWidth() * 0.9); this.gravity = Gravity.TOP | Gravity.LEFT; text = new SpannableStringBuilder() .append(description) .append("\n") .append(context.getResources().getText(guide)); this.dismissOnTouch = true; this.dismissOnClose = false; this.inputView = inputView; window = new PopupWindow(context); window.setBackgroundDrawable(null); LayoutInflater inflate = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); textView = (TextView) inflate.inflate(R.layout.bubble_text, null); textView.setBackgroundDrawable(bubbleBackground); textView.setText(text); if (leftAlign) { textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); } window.setContentView(textView); window.setFocusable(false); window.setTouchable(true); window.setOutsideTouchable(false); } private int chooseSize(PopupWindow pop, View parentView, CharSequence text, TextView tv) { int wid = tv.getPaddingLeft() + tv.getPaddingRight(); int ht = tv.getPaddingTop() + tv.getPaddingBottom(); /* * Figure out how big the text would be if we laid it out to the * full width of this view minus the border. */ int cap = width - wid; Layout l = new StaticLayout(text, tv.getPaint(), cap, Layout.Alignment.ALIGN_NORMAL, 1, 0, true); float max = 0; for (int i = 0; i < l.getLineCount(); i++) { max = Math.max(max, l.getLineWidth(i)); } /* * Now set the popup size to be big enough for the text plus the border. */ pop.setWidth(width); pop.setHeight(ht + l.getHeight()); return l.getHeight(); } void show(int offx, int offy) { int textHeight = chooseSize(window, inputView, text, textView); offy -= textView.getPaddingTop() + textHeight; if (inputView.getVisibility() == View.VISIBLE && inputView.getWindowVisibility() == View.VISIBLE) { try { if ((gravity & Gravity.BOTTOM) == Gravity.BOTTOM) offy -= window.getHeight(); if ((gravity & Gravity.RIGHT) == Gravity.RIGHT) offx -= window.getWidth(); textView.setOnTouchListener(new View.OnTouchListener() { public boolean onTouch(View view, MotionEvent me) { boolean ret = !mEnableKeyTouch; switch (me.getAction()) { case MotionEvent.ACTION_UP: if (mBubbleIndex >= mBubbles.size()) { mInputView.setOnTouchListener(null); } else { TutorialJAJP.this.next(); } break; default: break; } return ret; } }); window.showAtLocation(inputView, Gravity.NO_GRAVITY, x + offx, y + offy); } catch (Exception e) { } } } void hide() { if (window.isShowing()) { textView.setOnTouchListener(null); window.dismiss(); } } boolean isShowing() { return window.isShowing(); } } /** Constructor */ public TutorialJAJP(OpenWnnJAJP ime, View inputView, DefaultSoftKeyboardJAJP inputManager) { mInputManager = inputManager; mInputView = inputView; mIme = ime; Context context = inputView.getContext(); int inputWidth = inputView.getWidth(); Resources r = inputView.getContext().getResources(); final int x = inputWidth / 20; r.getDimensionPixelOffset(R.dimen.bubble_pointer_offset); SpannableStringBuilder spannable = new SpannableStringBuilder(); Bubble button; spannable.clear(); spannable.append(r.getText(R.string.tip_to_step1)); setSpan(spannable, "\u25cb", R.drawable.tutorial_12key_key); button = new Bubble(context, inputView, R.drawable.dialog_bubble, x, 0, spannable, R.string.touch_to_continue, false); mBubbles.add(button); spannable.clear(); spannable.append(r.getText(R.string.tip_to_step2_a)); setSpan(spannable, "\u25cb", R.drawable.tutorial_12key_toggle); button = new Bubble(context, inputView, R.drawable.dialog_bubble, x, 0, spannable, R.string.touch_to_continue, true); mBubbles.add(button); spannable.append(r.getText(R.string.tip_to_step2_b)); setSpan(spannable, "\u2192", R.drawable.tutorial_12key_right); button = new Bubble(context, inputView, R.drawable.dialog_bubble, x, 0, spannable, R.string.touch_to_continue, true); mBubbles.add(button); spannable.append(r.getText(R.string.tip_to_step2_c)); setSpan(spannable, "\u25cb", R.drawable.tutorial_12key_toggle); button = new Bubble(context, inputView, R.drawable.dialog_bubble, x, 0, spannable, R.string.touch_to_continue, true); mBubbles.add(button); spannable.append(r.getText(R.string.tip_to_step2_d)); setSpan(spannable, "\u25a0", R.drawable.tutorial_12key_space_jp); setSpan(spannable, "\u2193", R.drawable.tutorial_12key_enter); button = new Bubble(context, inputView, R.drawable.dialog_bubble, x, 0, spannable, R.string.touch_to_continue, true); mBubbles.add(button); spannable.clear(); spannable.append(r.getText(R.string.tip_to_step3_a)); setSpan(spannable, "\u25a0", R.drawable.tutorial_12key_mode); button = new Bubble(context, inputView, R.drawable.dialog_bubble_moji, x, 0, spannable, R.string.touch_to_continue, false); mBubbles.add(button); button = new Bubble(context, inputView, R.drawable.dialog_bubble_moji, x, 0, R.string.tip_to_step3_b, R.string.touch_to_continue); mBubbles.add(button); button = new Bubble(context, inputView, R.drawable.dialog_bubble_moji, x, 0, R.string.tip_to_step3_c, R.string.touch_to_continue); mBubbles.add(button); spannable.clear(); spannable.append(r.getText(R.string.tip_to_step4)); setSpan(spannable, "\u25a0", R.drawable.tutorial_12key_mode); button = new Bubble(context, inputView, R.drawable.dialog_bubble_moji, x, 0, spannable, R.string.touch_to_try, false); mBubbles.add(button); spannable.clear(); spannable.append(r.getText(R.string.tip_to_step5)); setSpan(spannable, "\u2190", R.drawable.tutorial_back); button = new Bubble(context, inputView, R.drawable.dialog_bubble, x, 0, spannable, R.string.touch_to_continue, false); mBubbles.add(button); button = new Bubble(context, inputView, R.drawable.dialog_bubble, x, 0, R.string.tip_to_step6, R.string.touch_to_finish); mBubbles.add(button); } private void setSpan(SpannableStringBuilder spannable, String marker, int imageResourceId) { String text = spannable.toString(); int target = text.indexOf(marker); while (0 <= target) { ImageSpan span = new ImageSpan(mIme, imageResourceId, DynamicDrawableSpan.ALIGN_BOTTOM); spannable.setSpan(span, target, target + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); target = text.indexOf(marker, target + 1); } } public void start() { mInputView.getLocationInWindow(mLocation); mBubbleIndex = -1; mInputView.setOnTouchListener(this); next(); } boolean next() { if (mBubbleIndex >= 0) { if (!mBubbles.get(mBubbleIndex).isShowing()) { return true; } for (int i = 0; i <= mBubbleIndex; i++) { mBubbles.get(i).hide(); } } mBubbleIndex++; if (mBubbleIndex >= mBubbles.size()) { mEnableKeyTouch = true; mIme.sendDownUpKeyEvents(-1); mIme.tutorialDone(); return false; } if ((6 <= mBubbleIndex) && (mBubbleIndex <= 8)) { mInputManager.nextKeyMode(); } if (mBubbleIndex == LONG_PRESS_INDEX) { mEnableKeyTouch = true; } else if (LONG_PRESS_INDEX < mBubbleIndex) { mEnableKeyTouch = false; } mHandler.sendMessageDelayed( mHandler.obtainMessage(MSG_SHOW_BUBBLE, mBubbles.get(mBubbleIndex)), 500); return true; } void hide() { for (int i = 0; i < mBubbles.size(); i++) { mBubbles.get(i).hide(); } mInputView.setOnTouchListener(null); } public boolean close() { mHandler.removeMessages(MSG_SHOW_BUBBLE); hide(); return true; } public boolean onTouch(View v, MotionEvent event) { boolean ret = !mEnableKeyTouch; if (event.getAction() == MotionEvent.ACTION_UP) { if (mBubbleIndex >= mBubbles.size()) { mInputView.setOnTouchListener(null); } else { if (mBubbleIndex != LONG_PRESS_INDEX) { next(); } } } return ret; } }