package com.ghostsq.commander;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import com.ghostsq.commander.adapters.CA;
import com.ghostsq.commander.adapters.CommanderAdapter;
import com.ghostsq.commander.favorites.Favorite;
import com.ghostsq.commander.utils.Credentials;
import com.ghostsq.commander.utils.Utils;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.InputFilter;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.Window;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class Editor extends Activity implements TextWatcher {
private final static String TAG = "EditorActivity";
private final static String SP_ENC = "encoding";
final static int MENU_SAVE = 214, MENU_SVAS = 212, MENU_RELD = 439, MENU_WRAP = 241, MENU_ENC = 363, MENU_EXIT = 323;
// final static String URI = "URIfileForEdit";
private EditText te;
private boolean horScroll = true;
public Uri uri;
public CommanderAdapter ca;
public boolean dirty = false;
public String encoding;
private DataLoadTask loader = null;
/** Called when the activity is first created. */
@Override
public void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
try {
SharedPreferences prefs = getPreferences( MODE_PRIVATE );
if( prefs != null )
encoding = prefs.getString( SP_ENC, "" );
boolean ct_enabled = requestWindowFeature( Window.FEATURE_CUSTOM_TITLE );
setContentView(R.layout.editor);
te = (EditText)findViewById( R.id.editor );
te.addTextChangedListener( this );
// experimental!
te.setFilters( new InputFilter[] { new InputFilter.LengthFilter(0x7FFFFFFF) } );
SharedPreferences shared_pref = PreferenceManager.getDefaultSharedPreferences( this );
int fs = Integer.parseInt( shared_pref != null ? shared_pref.getString( "font_size", "12" ) : "12" );
te.setTextSize( fs );
ColorsKeeper ck = new ColorsKeeper( this );
ck.restore();
te.setBackgroundColor( ck.bgrColor );
te.setTextColor( ck.fgrColor );
if( ct_enabled ) {
getWindow().setFeatureInt( Window.FEATURE_CUSTOM_TITLE, R.layout.atitle );
TextView act_name_tv = (TextView)findViewById( R.id.act_name );
if( act_name_tv != null )
act_name_tv.setText( R.string.editor_label );
}
uri = getIntent().getData();
loader = new DataLoadTask();
loader.execute();
TextView file_name_tv = (TextView)findViewById( R.id.file_name );
if( file_name_tv!= null )
file_name_tv.setText( " - " + uri.getPath() );
}
catch( Exception e ) {
Log.e( TAG, "", e );
finish();
}
}
@Override
protected void onPause() {
super.onPause();
SharedPreferences.Editor editor = getPreferences( MODE_PRIVATE ).edit();
editor.putString( SP_ENC, encoding == null ? "" : encoding );
editor.commit();
}
@Override
protected void onStop() {
Log.d( TAG, "onStop" );
super.onStop();
if( ca != null )
ca.prepareToDestroy();
ca = null;
}
@Override
protected void onDestroy() {
super.onDestroy();
if( loader != null )
loader.cancel( true );
}
@Override
public boolean onKeyDown( int keyCode, KeyEvent event ) {
switch( keyCode ) {
case KeyEvent.KEYCODE_BACK:
if( dirty ) {
DialogInterface.OnClickListener ocl = new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialog, int which_button ) {
if( which_button == DialogInterface.BUTTON_POSITIVE ) {
new DataSaveTask( true ).execute( uri );
}
else if( which_button == DialogInterface.BUTTON_NEGATIVE ) {
Editor.this.finish();
}
}
};
new AlertDialog.Builder( this )
.setIcon( android.R.drawable.ic_dialog_alert )
.setTitle( R.string.save )
.setMessage( R.string.not_saved )
.setPositiveButton( R.string.save, ocl )
.setNegativeButton( R.string.dialog_cancel, ocl )
.show();
return true;
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onPrepareOptionsMenu( Menu menu ) {
menu.clear();
menu.add( Menu.NONE, MENU_SAVE, Menu.NONE, getString( R.string.save ) ).setIcon( android.R.drawable.ic_menu_save );
menu.add( Menu.NONE, MENU_SVAS, Menu.NONE, getString( R.string.save_as ) ).setIcon( android.R.drawable.ic_menu_save );
menu.add( Menu.NONE, MENU_RELD, Menu.NONE, getString( R.string.revert ) ).setIcon( android.R.drawable.ic_menu_revert );
menu.add( Menu.NONE, MENU_WRAP, Menu.NONE, getString( R.string.wrap ) ).setIcon( R.drawable.wrap );
menu.add( Menu.NONE, MENU_ENC, Menu.NONE, Utils.getEncodingDescr( this, encoding,
Utils.ENC_DESC_MODE_BRIEF ) ).setIcon(android.R.drawable.ic_menu_sort_alphabetically );
menu.add( Menu.NONE, MENU_EXIT, Menu.NONE, getString( R.string.exit ) ).setIcon( android.R.drawable.ic_notification_clear_all );
return true;
}
@Override
public boolean onMenuItemSelected( int featureId, MenuItem item ) {
switch( item.getItemId() ) {
case MENU_SAVE:
new DataSaveTask( false ).execute( uri );
return true;
case MENU_SVAS:
try {
LayoutInflater factory = LayoutInflater.from( this );
View iv = factory.inflate( R.layout.input, null );
if( iv != null ) {
TextView prompt = (TextView)iv.findViewById( R.id.prompt );
final EditText edit = (EditText)iv.findViewById( R.id.edit_field );
prompt.setText( R.string.newf_prompt );
edit.setText( uri.toString() );
new AlertDialog.Builder( this )
.setTitle( R.string.save_as )
.setView( iv )
.setPositiveButton( R.string.save, new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialog, int i ) {
new DataSaveTask( false ).execute( Uri.parse( edit.getText().toString() ) );
}
} ).setNegativeButton( R.string.dialog_cancel, null ).show();
}
} catch( Throwable e ) {
Log.e( TAG, "", e );
}
return true;
case MENU_RELD:
loader = new DataLoadTask();
loader.execute();
return true;
case MENU_ENC: {
int cen = Integer.parseInt( Utils.getEncodingDescr( this, encoding, Utils.ENC_DESC_MODE_NUMB ) );
new AlertDialog.Builder( this )
.setTitle( R.string.encoding )
.setSingleChoiceItems( R.array.encoding, cen, new DialogInterface.OnClickListener() {
public void onClick( DialogInterface dialog, int i ) {
dialog.dismiss();
encoding = getResources().getStringArray( R.array.encoding_vals )[i];
Log.i( TAG, "Chosen encoding: " + encoding );
Editor.this.showMessage( getString( R.string.encoding_set, encoding ) );
}
}).show();
}
return true;
case MENU_WRAP:
try {
EditText te = (EditText)findViewById( R.id.editor );
horScroll = horScroll ? false : true;
te.setHorizontallyScrolling( horScroll );
}
catch( Exception e ) {
System.err.println("Exception: " + e );
}
return true;
case MENU_EXIT:
// TODO: warn if text was changed, but not saved!
finish();
}
return super.onMenuItemSelected(featureId, item);
}
public final void showMessage( String s ) {
Toast.makeText(this, s, Toast.LENGTH_LONG).show();
}
private class DataLoadTask extends AsyncTask<Void, String, CharSequence> {
private ProgressDialog pd;
@Override
protected void onPreExecute() {
pd = ProgressDialog.show( Editor.this, "", getString( R.string.loading ), true, true );
}
@Override
protected CharSequence doInBackground( Void... v ) {
Uri uri = Editor.this.uri;
try {
final String scheme = uri.getScheme();
InputStream is = null;
if( Editor.this.ca == null ) {
int type_id = CA.GetAdapterTypeId( scheme );
Editor.this.ca = CA.CreateAdapterInstance( type_id, Editor.this );
}
if( Editor.this.ca != null ) {
Credentials crd = null;
try {
crd = (Credentials)Editor.this.getIntent().getParcelableExtra( Credentials.KEY );
} catch( Exception e ) {
Log.e( TAG, "on taking credentials from parcel", e );
}
Editor.this.ca.setCredentials( crd );
is = Editor.this.ca.getContent( uri );
}
if( is != null ) {
CharSequence cs = Utils.readStreamToBuffer( is, encoding );
if( Editor.this.ca != null ) {
Editor.this.ca.closeStream( is );
}
else
is.close();
return cs;
}
publishProgress( getString( R.string.rtexcept, uri.toString() ) );
} catch( OutOfMemoryError e ) {
Log.e( TAG, uri.toString(), e );
publishProgress( getString( R.string.too_big_file, uri.getPath() ) );
} catch( Throwable e ) {
Log.e( TAG, uri.toString(), e );
publishProgress( getString( R.string.failed ) + e.getLocalizedMessage() );
}
return null;
}
@Override
protected void onProgressUpdate( String... err ) {
if( err.length > 0 ) Editor.this.showMessage( err[0] );
}
@Override
protected void onPostExecute( CharSequence cs ) {
pd.cancel();
Editor.this.te.setText( cs );
Editor.this.dirty = false;
Editor.this.loader = null;
}
}
private class DataSaveTask extends AsyncTask<Uri, String, Boolean> {
private ProgressDialog pd;
private boolean close_on_finish;
DataSaveTask( boolean close_on_finish_ ) {
close_on_finish = close_on_finish_;
}
@Override
protected void onPreExecute() {
pd = ProgressDialog.show( Editor.this, "", getString( R.string.wait ), true, true );
}
@Override
protected Boolean doInBackground( Uri... save_uri_ ) {
Uri save_uri = save_uri_.length > 0 ? save_uri_[0] : null;
if( save_uri == null || Editor.this.ca == null ) return false;
Credentials crd = null;
try {
crd = (Credentials)Editor.this.getIntent().getParcelableExtra( Credentials.KEY );
} catch( Exception e ) {
Log.e( TAG, "on taking credentials from parcel", e );
}
Editor.this.ca.setCredentials( crd );
OutputStream os = Editor.this.ca.saveContent( save_uri );
if( os == null ) return false;
try {
final int BUF_SIZE = 16*1024;
OutputStreamWriter osw = Editor.this.encoding != null && Editor.this.encoding.length() != 0 ?
new OutputStreamWriter( os, Editor.this.encoding ) :
new OutputStreamWriter( os );
Editable e = Editor.this.te.getText();
int len = e.length();
if( len < BUF_SIZE ) {
osw.write( e.toString() );
osw.flush();
} else {
char[] chars = new char[BUF_SIZE];
int start = 0, end = BUF_SIZE;
while( start < len-1 ) {
e.getChars( start, end, chars, 0 );
osw.write( chars, 0, end - start );
start = end;
end += BUF_SIZE;
if( end > len )
end = len-1;
}
}
//Log.v( TAG, "Data is sent to the stream" );
Editor.this.ca.closeStream( os );
File f = new File( save_uri.getPath() );
publishProgress( getString( R.string.saved, f.getName() ) );
return true;
} catch( Throwable e ) {
Log.e( TAG, Favorite.screenPwd( save_uri ), e );
}
return false;
}
@Override
protected void onProgressUpdate( String... err ) {
if( err.length > 0 ) Editor.this.showMessage( err[0] );
}
@Override
protected void onPostExecute( Boolean succeeded ) {
pd.cancel();
if( succeeded )
Editor.this.dirty = false;
else
Editor.this.showMessage( Editor.this.getString( R.string.cant_save ) );
if( close_on_finish )
Editor.this.finish();
}
}
@Override
public void afterTextChanged( Editable s ) {
dirty = true;
}
@Override
public void beforeTextChanged( CharSequence s, int start, int count, int after ) {
}
@Override
public void onTextChanged( CharSequence s, int start, int before, int count ) {
}
}