private boolean mIsSelectingText = false;
+ private float mDensity;
+
private float mScaledDensity;
private static final int SELECT_TEXT_OFFSET_Y = -40;
private int mSelXAnchor = -1;
return mUpdateNotify;
}
- public EmulatorView(Context context) {
+ public EmulatorView(Context context, TermSession session, TermViewFlipper viewFlipper, DisplayMetrics metrics) {
super(context);
- commonConstructor();
+ commonConstructor(session, viewFlipper);
+ setDensity(metrics);
}
- public void setScaledDensity(float scaledDensity) {
- mScaledDensity = scaledDensity;
+ public void setDensity(DisplayMetrics metrics) {
+ mDensity = metrics.density;
+ mScaledDensity = metrics.scaledDensity;
}
public void onResume() {
}
}
- public void updatePrefs(TermSettings settings, DisplayMetrics metrics) {
+ public void updatePrefs(TermSettings settings) {
mSettings = settings;
- setTextSize((int) (mSettings.getFontSize() * metrics.density));
+ setTextSize((int) (mSettings.getFontSize() * mDensity));
setCursorStyle(mSettings.getCursorStyle(), mSettings.getCursorBlink());
setUseCookedIME(mSettings.useCookedIME());
setColors();
updateText();
}
- public String getTranscriptText() {
- return mEmulator.getTranscriptText();
- }
-
public void resetTerminal() {
mEmulator.reset();
invalidate();
return mEmulator.getKeypadApplicationMode();
}
- public EmulatorView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public EmulatorView(Context context, AttributeSet attrs,
- int defStyle) {
- super(context, attrs, defStyle);
- // TypedArray a =
- // context.obtainStyledAttributes(android.R.styleable.View);
- // initializeScrollbars(a);
- // a.recycle();
- commonConstructor();
- }
-
- private void commonConstructor() {
+ private void commonConstructor(TermSession session, TermViewFlipper viewFlipper) {
mTextRenderer = null;
mCursorPaint = new Paint();
mCursorPaint.setARGB(255,128,128,128);
mGestureDetector = new GestureDetector(this);
// mGestureDetector.setIsLongpressEnabled(false);
setVerticalScrollBarEnabled(true);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+
+ initialize(session, viewFlipper);
}
@Override
*
* @param session The terminal session this view will be displaying
*/
- public void initialize(TermSession session) {
+ private void initialize(TermSession session, TermViewFlipper viewFlipper) {
mTermSession = session;
mTranscriptScreen = session.getTranscriptScreen();
mEmulator = session.getEmulator();
mForeground = TermSettings.WHITE;
mBackground = TermSettings.BLACK;
updateText();
+
+ requestFocus();
}
/**
package jackpal.androidterm;
import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
import android.app.Activity;
import android.app.AlertDialog;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.text.ClipboardManager;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
+import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
+import android.widget.FrameLayout;
import jackpal.androidterm.session.TermSession;
import jackpal.androidterm.util.TermSettings;
public class Term extends Activity {
/**
- * Our main view. Displays the emulated terminal screen.
+ * The ViewFlipper which holds the collection of EmulatorView widgets.
*/
- private EmulatorView mEmulatorView;
+ private TermViewFlipper mViewFlipper;
/**
- * The name of our emulator view in the view resource.
+ * The name of the ViewFlipper in the resources.
*/
- private static final int EMULATOR_VIEW = R.id.emulatorView;
+ private static final int VIEW_FLIPPER = R.id.view_flipper;
- private TermSession mTermSession;
-
- private String mInitialCommand;
+ private ArrayList<TermSession> mTermSessions;
private SharedPreferences mPrefs;
private TermSettings mSettings;
private boolean mAlreadyStarted = false;
- public TermService mTermService;
private Intent TSIntent;
private PowerManager.WakeLock mWakeLock;
private WifiManager.WifiLock mWifiLock;
+ private TermService mTermService;
+ private ServiceConnection mTSConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ Log.i(TermDebug.LOG_TAG, "Bound to TermService");
+ TermService.TSBinder binder = (TermService.TSBinder) service;
+ mTermService = binder.getService();
+ populateViewFlipper();
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName arg0) {
+ mTermService = null;
+ }
+ };
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
TSIntent = new Intent(this, TermService.class);
startService(TSIntent);
- setContentView(R.layout.term_activity);
-
- mEmulatorView = (EmulatorView) findViewById(EMULATOR_VIEW);
-
- /* Check whether we've received an initial command from the
- * launching application
- */
- mInitialCommand = mSettings.getInitialCommand();
- String iInitialCommand = getIntent().getStringExtra("jackpal.androidterm.iInitialCommand");
- if (iInitialCommand != null) {
- if (mInitialCommand != null) {
- mInitialCommand += "\r" + iInitialCommand;
- } else {
- mInitialCommand = iInitialCommand;
- }
+ if (!bindService(TSIntent, mTSConnection, BIND_AUTO_CREATE)) {
+ Log.w(TermDebug.LOG_TAG, "bind to service failed!");
}
- mTermSession = new TermSession(mSettings, mEmulatorView.getUpdateCallback(), mInitialCommand);
- mEmulatorView.initialize(mTermSession);
-
- DisplayMetrics metrics = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(metrics);
- mEmulatorView.setScaledDensity(metrics.scaledDensity);
-
- mEmulatorView.setFocusable(true);
- mEmulatorView.setFocusableInTouchMode(true);
- mEmulatorView.requestFocus();
-
- registerForContextMenu(mEmulatorView);
+ setContentView(R.layout.term_activity);
+ mViewFlipper = (TermViewFlipper) findViewById(VIEW_FLIPPER);
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TermDebug.LOG_TAG);
mAlreadyStarted = true;
}
+ private void populateViewFlipper() {
+ if (mTermService != null) {
+ mTermSessions = mTermService.getSessions();
+
+ if (mTermSessions.size() == 0) {
+ mTermSessions.add(createTermSession());
+ }
+
+ for (TermSession session : mTermSessions) {
+ EmulatorView view = createEmulatorView(session);
+ mViewFlipper.addView(view);
+ mViewFlipper.showNext();
+ }
+
+ updatePrefs();
+ }
+ }
+
@Override
public void onDestroy() {
super.onDestroy();
- mTermSession.finish();
+ mViewFlipper.removeAllViews();
+ unbindService(mTSConnection);
+ stopService(TSIntent);
+ mTermService = null;
+ mTSConnection = null;
if (mWakeLock.isHeld()) {
mWakeLock.release();
}
if (mWifiLock.isHeld()) {
mWifiLock.release();
}
- stopService(TSIntent);
}
private void restart() {
finish();
}
+ private TermSession createTermSession() {
+ /* Check whether we've received an initial command from the
+ * launching application
+ */
+ String initialCommand = mSettings.getInitialCommand();
+ String iInitialCommand = getIntent().getStringExtra("jackpal.androidterm.iInitialCommand");
+ if (iInitialCommand != null) {
+ if (initialCommand != null) {
+ initialCommand += "\r" + iInitialCommand;
+ } else {
+ initialCommand = iInitialCommand;
+ }
+ }
+
+ return new TermSession(mSettings, null, initialCommand);
+ }
+
+ private EmulatorView createEmulatorView(TermSession session) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics(metrics);
+ EmulatorView emulatorView = new EmulatorView(this, session, mViewFlipper, metrics);
+
+ FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ Gravity.LEFT
+ );
+ emulatorView.setLayoutParams(params);
+
+ session.setUpdateCallback(emulatorView.getUpdateCallback());
+
+ registerForContextMenu(emulatorView);
+
+ return emulatorView;
+ }
+
+ private TermSession getCurrentTermSession() {
+ return mTermSessions.get(mViewFlipper.getDisplayedChild());
+ }
+
+ private EmulatorView getCurrentEmulatorView() {
+ return (EmulatorView) mViewFlipper.getCurrentView();
+ }
+
private void updatePrefs() {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
- mEmulatorView.updatePrefs(mSettings, metrics);
+
+ for (View v : mViewFlipper) {
+ ((EmulatorView) v).updatePrefs(mSettings, metrics);
+ }
{
Window win = getWindow();
WindowManager.LayoutParams params = win.getAttributes();
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
mSettings.readPrefs(mPrefs);
updatePrefs();
- mEmulatorView.onResume();
+
+ mViewFlipper.resumeCurrentView();
}
@Override
public void onPause() {
super.onPause();
- mEmulatorView.onPause();
+
+ mViewFlipper.pauseCurrentView();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- mEmulatorView.updateSize(true);
+ EmulatorView v = (EmulatorView) mViewFlipper.getCurrentView();
+ if (v != null) {
+ v.updateSize(true);
+ }
}
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
case SELECT_TEXT_ID:
- mEmulatorView.toggleSelectingText();
+ getCurrentEmulatorView().toggleSelectingText();
return true;
case COPY_ALL_ID:
doCopyAll();
new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"
+ addr));
- intent.putExtra("body", mEmulatorView.getTranscriptText().trim());
+ intent.putExtra("body", getCurrentTermSession().getTranscriptText().trim());
startActivity(intent);
}
private void doCopyAll() {
ClipboardManager clip = (ClipboardManager)
getSystemService(Context.CLIPBOARD_SERVICE);
- clip.setText(mEmulatorView.getTranscriptText().trim());
+ clip.setText(getCurrentTermSession().getTranscriptText().trim());
}
private void doPaste() {
Log.e(TermDebug.LOG_TAG, "UTF-8 encoding not found.");
return;
}
- mTermSession.write(paste.toString());
+ getCurrentTermSession().write(paste.toString());
}
private void doDocumentKeys() {
--- /dev/null
+/*
+ * Copyright (C) 2011 Steven Luo
+ *
+ * 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 jackpal.androidterm;
+
+import java.util.Iterator;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Toast;
+import android.widget.ViewFlipper;
+
+public class TermViewFlipper extends ViewFlipper implements Iterable<View> {
+ private Context context;
+ private Toast mToast;
+
+ class ViewFlipperIterator implements Iterator<View> {
+ int pos = 0;
+
+ @Override
+ public boolean hasNext() {
+ return (pos < getChildCount());
+ }
+
+ @Override
+ public View next() {
+ return getChildAt(pos++);
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ public TermViewFlipper(Context context) {
+ super(context);
+ this.context = context;
+ }
+
+ public TermViewFlipper(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ this.context = context;
+ }
+
+ @Override
+ public Iterator<View> iterator() {
+ return new ViewFlipperIterator();
+ }
+
+ public void pauseCurrentView() {
+ EmulatorView view = (EmulatorView) getCurrentView();
+ if (view == null) {
+ return;
+ }
+ view.onPause();
+ }
+
+ public void resumeCurrentView() {
+ EmulatorView view = (EmulatorView) getCurrentView();
+ if (view == null) {
+ return;
+ }
+ view.onResume();
+ }
+
+ private void showTitle() {
+ if (getChildCount() == 0) {
+ return;
+ }
+ String title = "Window " + (getDisplayedChild()+1);
+ if (mToast == null) {
+ mToast = Toast.makeText(context, title, Toast.LENGTH_SHORT);
+ } else {
+ mToast.setText(title);
+ }
+ mToast.show();
+ }
+
+ @Override
+ public void showPrevious() {
+ pauseCurrentView();
+ super.showPrevious();
+ showTitle();
+ resumeCurrentView();
+ }
+
+ @Override
+ public void showNext() {
+ pauseCurrentView();
+ super.showNext();
+ showTitle();
+ resumeCurrentView();
+ }
+
+ @Override
+ public void setDisplayedChild(int position) {
+ pauseCurrentView();
+ super.setDisplayedChild(position);
+ showTitle();
+ resumeCurrentView();
+ }
+}