Home | History | Annotate | Download | only in terminal
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      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 package com.android.terminal;
     18 
     19 import static com.android.terminal.Terminal.TAG;
     20 
     21 import android.app.Activity;
     22 import android.content.ComponentName;
     23 import android.content.Context;
     24 import android.content.Intent;
     25 import android.content.ServiceConnection;
     26 import android.os.Bundle;
     27 import android.os.IBinder;
     28 import android.os.Parcelable;
     29 import android.support.v4.view.PagerAdapter;
     30 import android.support.v4.view.PagerTitleStrip;
     31 import android.support.v4.view.ViewPager;
     32 import android.util.Log;
     33 import android.util.SparseArray;
     34 import android.view.Menu;
     35 import android.view.MenuItem;
     36 import android.view.View;
     37 import android.view.ViewGroup;
     38 
     39 /**
     40  * Activity that displays all {@link Terminal} instances running in a bound
     41  * {@link TerminalService}.
     42  */
     43 public class TerminalActivity extends Activity {
     44 
     45     private TerminalService mService;
     46 
     47     private ViewPager mPager;
     48     private PagerTitleStrip mTitles;
     49 
     50     private final ServiceConnection mServiceConn = new ServiceConnection() {
     51         @Override
     52         public void onServiceConnected(ComponentName name, IBinder service) {
     53             mService = ((TerminalService.ServiceBinder) service).getService();
     54 
     55             final int size = mService.getTerminals().size();
     56             Log.d(TAG, "Bound to service with " + size + " active terminals");
     57 
     58             // Give ourselves at least one terminal session
     59             if (size == 0) {
     60                 mService.createTerminal();
     61             }
     62 
     63             // Bind UI to known terminals
     64             mTermAdapter.notifyDataSetChanged();
     65             invalidateOptionsMenu();
     66         }
     67 
     68         @Override
     69         public void onServiceDisconnected(ComponentName name) {
     70             mService = null;
     71             throw new RuntimeException("Service in same process disconnected?");
     72         }
     73     };
     74 
     75     private final PagerAdapter mTermAdapter = new PagerAdapter() {
     76         private SparseArray<SparseArray<Parcelable>>
     77                 mSavedState = new SparseArray<SparseArray<Parcelable>>();
     78 
     79         @Override
     80         public int getCount() {
     81             if (mService != null) {
     82                 return mService.getTerminals().size();
     83             } else {
     84                 return 0;
     85             }
     86         }
     87 
     88         @Override
     89         public Object instantiateItem(ViewGroup container, int position) {
     90             final TerminalView view = new TerminalView(container.getContext());
     91             view.setId(android.R.id.list);
     92 
     93             final Terminal term = mService.getTerminals().valueAt(position);
     94             view.setTerminal(term);
     95 
     96             final SparseArray<Parcelable> state = mSavedState.get(term.key);
     97             if (state != null) {
     98                 view.restoreHierarchyState(state);
     99             }
    100 
    101             container.addView(view);
    102             return view;
    103         }
    104 
    105         @Override
    106         public void destroyItem(ViewGroup container, int position, Object object) {
    107             final TerminalView view = (TerminalView) object;
    108 
    109             final int key = view.getTerminal().key;
    110             SparseArray<Parcelable> state = mSavedState.get(key);
    111             if (state == null) {
    112                 state = new SparseArray<Parcelable>();
    113                 mSavedState.put(key, state);
    114             }
    115             view.saveHierarchyState(state);
    116 
    117             view.setTerminal(null);
    118             container.removeView(view);
    119         }
    120 
    121         @Override
    122         public int getItemPosition(Object object) {
    123             final TerminalView view = (TerminalView) object;
    124             final int key = view.getTerminal().key;
    125             final int index = mService.getTerminals().indexOfKey(key);
    126             if (index == -1) {
    127                 return POSITION_NONE;
    128             } else {
    129                 return index;
    130             }
    131         }
    132 
    133         @Override
    134         public boolean isViewFromObject(View view, Object object) {
    135             return view == object;
    136         }
    137 
    138         @Override
    139         public CharSequence getPageTitle(int position) {
    140             return mService.getTerminals().valueAt(position).getTitle();
    141         }
    142     };
    143 
    144     @Override
    145     protected void onCreate(Bundle savedInstanceState) {
    146         super.onCreate(savedInstanceState);
    147 
    148         setContentView(R.layout.activity);
    149 
    150         mPager = (ViewPager) findViewById(R.id.pager);
    151         mTitles = (PagerTitleStrip) findViewById(R.id.titles);
    152 
    153         mPager.setAdapter(mTermAdapter);
    154     }
    155 
    156     @Override
    157     protected void onStart() {
    158         super.onStart();
    159         bindService(
    160                 new Intent(this, TerminalService.class), mServiceConn, Context.BIND_AUTO_CREATE);
    161     }
    162 
    163     @Override
    164     protected void onStop() {
    165         super.onStop();
    166         unbindService(mServiceConn);
    167     }
    168 
    169     @Override
    170     public boolean onCreateOptionsMenu(Menu menu) {
    171         getMenuInflater().inflate(R.menu.activity, menu);
    172         return true;
    173     }
    174 
    175     @Override
    176     public boolean onPrepareOptionsMenu(Menu menu) {
    177         super.onPrepareOptionsMenu(menu);
    178         menu.findItem(R.id.menu_close_tab).setEnabled(mTermAdapter.getCount() > 0);
    179         return true;
    180     }
    181 
    182     @Override
    183     public boolean onOptionsItemSelected(MenuItem item) {
    184         switch (item.getItemId()) {
    185             case R.id.menu_new_tab: {
    186                 mService.createTerminal();
    187                 mTermAdapter.notifyDataSetChanged();
    188                 invalidateOptionsMenu();
    189                 final int index = mService.getTerminals().size() - 1;
    190                 mPager.setCurrentItem(index, true);
    191                 return true;
    192             }
    193             case R.id.menu_close_tab: {
    194                 final int index = mPager.getCurrentItem();
    195                 final int key = mService.getTerminals().keyAt(index);
    196                 mService.destroyTerminal(key);
    197                 mTermAdapter.notifyDataSetChanged();
    198                 invalidateOptionsMenu();
    199                 return true;
    200             }
    201         }
    202         return false;
    203     }
    204 }
    205