From 00b00812cd0c883c2380065d7fda29512d5477f0 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Sun, 14 Apr 2013 16:16:49 -0700 Subject: Add scrollback support. Switch terminal rendering to use ListView, splitting each row into a TerminalLineView item. This leverages existing ListView display list optimizations when scrolling, and gives us fling and overscroll for free. However, the simple case of a single line scrolling requires an entire screen rebind. Added locking between I/O thread and UI thread to provide consistent view of terminal state. Snap to current upstream libvterm, which has updated scrollback API. Examine full cell style when building runs. Address terminals using "keys" instead of indicies, since ordering can shift. Save and restore instance state to remember scrollback position. Avoid crashing after closing last terminal. Remove unused callbacks. Bug: 8332387 Change-Id: I06468d16ae8e1ff8ac79b7115c7cb3f9434b3c0d --- src/com/android/terminal/TerminalActivity.java | 48 ++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 7 deletions(-) (limited to 'src/com/android/terminal/TerminalActivity.java') diff --git a/src/com/android/terminal/TerminalActivity.java b/src/com/android/terminal/TerminalActivity.java index 99d2be6..dd94d74 100644 --- a/src/com/android/terminal/TerminalActivity.java +++ b/src/com/android/terminal/TerminalActivity.java @@ -16,6 +16,8 @@ package com.android.terminal; +import static com.android.terminal.Terminal.TAG; + import android.app.Activity; import android.content.ComponentName; import android.content.Context; @@ -23,10 +25,12 @@ import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; +import android.os.Parcelable; import android.support.v4.view.PagerAdapter; import android.support.v4.view.PagerTitleStrip; import android.support.v4.view.ViewPager; import android.util.Log; +import android.util.SparseArray; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -37,7 +41,6 @@ import android.view.ViewGroup; * {@link TerminalService}. */ public class TerminalActivity extends Activity { - private static final String TAG = "Terminal"; private TerminalService mService; @@ -59,6 +62,7 @@ public class TerminalActivity extends Activity { // Bind UI to known terminals mTermAdapter.notifyDataSetChanged(); + invalidateOptionsMenu(); } @Override @@ -69,6 +73,9 @@ public class TerminalActivity extends Activity { }; private final PagerAdapter mTermAdapter = new PagerAdapter() { + private SparseArray> + mSavedState = new SparseArray>(); + @Override public int getCount() { if (mService != null) { @@ -80,9 +87,17 @@ public class TerminalActivity extends Activity { @Override public Object instantiateItem(ViewGroup container, int position) { - final Terminal term = mService.getTerminals().get(position); final TerminalView view = new TerminalView(container.getContext()); + view.setId(android.R.id.list); + + final Terminal term = mService.getTerminals().valueAt(position); view.setTerminal(term); + + final SparseArray state = mSavedState.get(term.key); + if (state != null) { + view.restoreHierarchyState(state); + } + container.addView(view); return view; } @@ -90,13 +105,24 @@ public class TerminalActivity extends Activity { @Override public void destroyItem(ViewGroup container, int position, Object object) { final TerminalView view = (TerminalView) object; + + final int key = view.getTerminal().key; + SparseArray state = mSavedState.get(key); + if (state == null) { + state = new SparseArray(); + mSavedState.put(key, state); + } + view.saveHierarchyState(state); + view.setTerminal(null); container.removeView(view); } @Override public int getItemPosition(Object object) { - final int index = mService.getTerminals().indexOf(object); + final TerminalView view = (TerminalView) object; + final int key = view.getTerminal().key; + final int index = mService.getTerminals().indexOfKey(key); if (index == -1) { return POSITION_NONE; } else { @@ -111,7 +137,7 @@ public class TerminalActivity extends Activity { @Override public CharSequence getPageTitle(int position) { - return mService.getTerminals().get(position).getTitle(); + return mService.getTerminals().valueAt(position).getTitle(); } }; @@ -146,22 +172,30 @@ public class TerminalActivity extends Activity { return true; } + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + menu.findItem(R.id.menu_close_tab).setEnabled(mTermAdapter.getCount() > 0); + return true; + } + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_new_tab: { mService.createTerminal(); mTermAdapter.notifyDataSetChanged(); + invalidateOptionsMenu(); final int index = mService.getTerminals().size() - 1; mPager.setCurrentItem(index, true); return true; } case R.id.menu_close_tab: { final int index = mPager.getCurrentItem(); - final Terminal term = mService.getTerminals().get(index); - mService.destroyTerminal(term); - // TODO: ask adamp about buggy zero item behavior + final int key = mService.getTerminals().keyAt(index); + mService.destroyTerminal(key); mTermAdapter.notifyDataSetChanged(); + invalidateOptionsMenu(); return true; } } -- cgit v1.2.3