ConversationDialogActivity.java revision cfd74d65d832137e20e193c960802afba73b5d38
1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/* 2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Copyright (C) 2008 The Android Open Source Project 3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License"); 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * you may not use this file except in compliance with the License. 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * You may obtain a copy of the License at 7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * http://www.apache.org/licenses/LICENSE-2.0 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * 10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * Unless required by applicable law or agreed to in writing, software 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS, 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * See the License for the specific language governing permissions and 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * limitations under the License. 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) */ 16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)package com.replica.replicaisland; 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import java.util.ArrayList; 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.app.Activity; 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.content.Context; 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.content.Intent; 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.graphics.Canvas; 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.graphics.Paint; 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.graphics.drawable.AnimationDrawable; 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.os.Bundle; 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.os.SystemClock; 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.text.SpannableStringBuilder; 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.text.TextUtils; 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.util.AttributeSet; 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.view.MotionEvent; 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.view.View; 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.widget.ImageView; 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import android.widget.TextView; 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import com.replica.replicaisland.ConversationUtils.Conversation; 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import com.replica.replicaisland.ConversationUtils.ConversationPage; 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)public class ConversationDialogActivity extends Activity { 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private final static float TEXT_CHARACTER_DELAY = 0.1f; 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private final static int TEXT_CHARACTER_DELAY_MS = (int)(TEXT_CHARACTER_DELAY * 1000); 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private ConversationUtils.Conversation mConversation; 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private ArrayList<ConversationUtils.ConversationPage> mPages; 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private int mCurrentPage; 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private ImageView mOkArrow; 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private AnimationDrawable mOkAnimation; 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) @Override 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) protected void onCreate(Bundle savedInstanceState) { 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) super.onCreate(savedInstanceState); 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) setContentView(R.layout.conversation_dialog); 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mOkArrow = (ImageView)findViewById(R.id.ok); 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mOkArrow.setBackgroundResource(R.anim.ui_button); 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mOkAnimation = (AnimationDrawable) mOkArrow.getBackground(); 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mOkArrow.setVisibility(View.INVISIBLE); 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) final Intent callingIntent = getIntent(); 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) final int levelRow = callingIntent.getIntExtra("levelRow", -1); 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) final int levelIndex = callingIntent.getIntExtra("levelIndex", -1); 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) final int index = callingIntent.getIntExtra("index", -1); 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) final int character = callingIntent.getIntExtra("character", 1); 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mPages = null; 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // LevelTree.get(mLevelRow, mLevelIndex).dialogResources.character2Entry.get(index) 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (levelRow != -1 && levelIndex != -1 && index != -1) { 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (character == 1) { 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mConversation = LevelTree.get(levelRow, levelIndex).dialogResources.character1Conversations.get(index); 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mConversation = LevelTree.get(levelRow, levelIndex).dialogResources.character2Conversations.get(index); 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TypewriterTextView tv = (TypewriterTextView)findViewById(R.id.typewritertext); 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) tv.setParentActivity(this); 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // bail 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) finish(); 82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private void formatPages(Conversation conversation, TextView textView) { 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Paint paint = new Paint(); 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) final int maxWidth = textView.getWidth(); 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) final int maxHeight = textView.getHeight(); 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) paint.setTextSize(textView.getTextSize()); 90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) paint.setTypeface(textView.getTypeface()); 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (int page = conversation.pages.size() - 1; page >= 0 ; page--) { 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ConversationUtils.ConversationPage currentPage = conversation.pages.get(page); 94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CharSequence text = currentPage.text; 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Iterate line by line through the text. Add \n if it gets too wide, 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // and split into a new page if it gets too long. 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int currentOffset = 0; 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int textLength = text.length(); 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SpannableStringBuilder spannedText = new SpannableStringBuilder(text); 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int lineCount = 0; 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) final float fontHeight = -paint.ascent() + paint.descent(); 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) final int maxLinesPerPage = (int)(maxHeight / fontHeight); 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CharSequence newline = "\n"; 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int addedPages = 0; 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int lastPageStart = 0; 106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) do { 107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int fittingChars = paint.breakText(text, currentOffset, textLength, true, maxWidth, null); 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (currentOffset + fittingChars < textLength) { 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) fittingChars -= 2; 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Text doesn't fit on the line. Insert a return after the last space. 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int lastSpace = TextUtils.lastIndexOf(text, ' ', currentOffset + fittingChars - 1); 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (lastSpace == -1) { 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // No spaces, just split at the last character. 115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) lastSpace = currentOffset + fittingChars - 1; 116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) spannedText.replace(lastSpace, lastSpace + 1, newline, 0, 1); 118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) lineCount++; 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) currentOffset = lastSpace + 1; 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) lineCount++; 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) currentOffset = textLength; 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (lineCount >= maxLinesPerPage || currentOffset >= textLength) { 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) lineCount = 0; 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (addedPages == 0) { 128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // overwrite the original page 129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) currentPage.text = spannedText.subSequence(lastPageStart, currentOffset); 130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // split into a new page 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ConversationPage newPage = new ConversationPage(); 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) newPage.imageResource = currentPage.imageResource; 134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) newPage.text = spannedText.subSequence(lastPageStart, currentOffset); 135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) newPage.title = currentPage.title; 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) conversation.pages.add(page + addedPages, newPage); 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) lastPageStart = currentOffset; 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) addedPages++; 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } while (currentOffset < textLength); 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Holy crap we did a lot of allocation there. 147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Runtime.getRuntime().gc(); 148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) @Override 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public boolean onTouchEvent(MotionEvent event) { 152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (event.getAction() == MotionEvent.ACTION_UP) { 153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TypewriterTextView tv = (TypewriterTextView)findViewById(R.id.typewritertext); 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (tv.getRemainingTime() > 0) { 156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) tv.snapToEnd(); 157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mCurrentPage++; 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (mCurrentPage < mPages.size()) { 160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) showPage(mPages.get(mCurrentPage)); 161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) finish(); 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Sleep so that the main thread doesn't get flooded with UI events. 167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) try { 168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Thread.sleep(32); 169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } catch (InterruptedException e) { 170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // No big deal if this sleep is interrupted. 171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) protected void showPage(ConversationUtils.ConversationPage page) { 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TypewriterTextView tv = (TypewriterTextView)findViewById(R.id.typewritertext); 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch tv.setTypewriterText(page.text); 178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mOkArrow.setVisibility(View.INVISIBLE); 180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mOkAnimation.start(); 181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) tv.setOkArrow(mOkArrow); 183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ImageView image = (ImageView)findViewById(R.id.speaker); 185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (page.imageResource != 0) { 186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) image.setImageResource(page.imageResource); 187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) image.setVisibility(View.VISIBLE); 188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) image.setVisibility(View.GONE); 190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TextView title = (TextView)findViewById(R.id.speakername); 193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (page.title != null) { 194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) title.setText(page.title); 195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) title.setVisibility(View.VISIBLE); 196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) title.setVisibility(View.GONE); 198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public void processText() { 203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!mConversation.splittingComplete) { 204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TextView textView = (TextView)findViewById(R.id.typewritertext); 205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) formatPages(mConversation, textView); 206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mConversation.splittingComplete = true; 207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (mPages == null) { 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mPages = mConversation.pages; 211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) showPage(mPages.get(0)); 212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mCurrentPage = 0; 214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public static class TypewriterTextView extends TextView { 219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private int mCurrentCharacter; 220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private long mLastTime; 221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private CharSequence mText; 222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private View mOkArrow; 2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private ConversationDialogActivity mParentActivity; // This really sucks. 224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public TypewriterTextView(Context context) { 226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) super(context); 227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public TypewriterTextView(Context context, AttributeSet attrs) { 230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) super(context, attrs); 231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public TypewriterTextView(Context context, AttributeSet attrs, int defStyle) { 234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) super(context, attrs, defStyle); 235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public void setParentActivity(ConversationDialogActivity parent) { 238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mParentActivity = parent; 239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public void setTypewriterText(CharSequence text) { 242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mText = text; 243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mCurrentCharacter = 0; 244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mLastTime = 0; 245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) postInvalidate(); 246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public long getRemainingTime() { 249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return (mText.length() - mCurrentCharacter) * TEXT_CHARACTER_DELAY_MS; 250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public void snapToEnd() { 253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mCurrentCharacter = mText.length() - 1; 254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public void setOkArrow(View arrow) { 257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mOkArrow = arrow; 258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) @Override 262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) protected void onSizeChanged(int w, int h, int oldw, int oldh) { 263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // We need to wait until layout has occurred before we can setup the 264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // text page. Ugh. Bidirectional dependency! 265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (mParentActivity != null) { 266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mParentActivity.processText(); 267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) super.onSizeChanged(w, h, oldw, oldh); 269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) @Override 272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public void onDraw(Canvas canvas) { 273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) final long time = SystemClock.uptimeMillis(); 274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) final long delta = time - mLastTime; 275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (delta > TEXT_CHARACTER_DELAY_MS) { 276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (mText != null) { 277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (mCurrentCharacter <= mText.length()) { 278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CharSequence subtext = mText.subSequence(0, mCurrentCharacter); 279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) setText(subtext, TextView.BufferType.SPANNABLE); 280f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mCurrentCharacter++; 281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) postInvalidateDelayed(TEXT_CHARACTER_DELAY_MS); 282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (mOkArrow != null) { 284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) mOkArrow.setVisibility(View.VISIBLE); 285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) super.onDraw(canvas); 290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)