android: move all sources to android folder, remove ant build system

This commit is contained in:
Alibek Omarov
2019-04-15 23:52:47 +03:00
parent 6d2d7a9d6d
commit 24632c0e69
88 changed files with 0 additions and 501 deletions
+260
View File
@@ -0,0 +1,260 @@
package in.celest.xash3d;
//Created by Solexid
import android.app.Activity;
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Bundle;
import android.os.Build;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.Button;
import java.io.File;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import su.xash.fwgslib.FWGSLib;
import in.celest.xash3d.hl.R;
public class FPicker extends Activity {
private File currentDir;
private FileArrayAdapter adapter;
static ListView delta;
public static final int sdk = Integer.valueOf(Build.VERSION.SDK);
static private Button mSelectBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ( sdk >= 21 )
super.setTheme( 0x01030224 );
else super.setTheme( 0x01030005 );
setContentView( R.layout.activity_fpicker );
String path = Environment.getExternalStorageDirectory().toString();
currentDir = new File( path );
mSelectBtn = ((Button)findViewById( R.id.button_fpicker_select ));
mSelectBtn.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
onFileClick(v);
}
});
FWGSLib.changeButtonsStyle((ViewGroup)mSelectBtn.getParent());
fill(currentDir);
}
private void fill(File folder)
{
mSelectBtn.setEnabled( false );
new Fill(folder).execute();
}
private class Fill extends AsyncTask<Void, Void, List<Item>>
{
File folder;
public Fill(File f)
{
folder = f;
}
protected List<Item> doInBackground(Void... voids)
{
File[] dirs = folder.listFiles();
List<Item> dir = new ArrayList<Item>();
while( dirs == null )
{
String parent = folder.getParent();
folder = new File( parent != null ? parent : Environment.getExternalStorageDirectory().toString() );
dirs = folder.listFiles();
}
for( File ff: dirs )
{
Date lastModDate = new Date(ff.lastModified());
DateFormat formater = DateFormat.getDateTimeInstance();
String date_modify = formater.format(lastModDate);
if(ff.isDirectory())
{
boolean isXashDir = false;
File[] fbuf = ff.listFiles();
int buf = 0;
if( fbuf != null && fbuf.length < 20 )
{
buf = fbuf.length;
for (File valves: fbuf)
{
if (valves.isDirectory() && valves.getName().contains("valve"))
isXashDir=true;
}
}
String num_item = getResources().getQuantityString(R.plurals.item_plurals, buf, buf);
dir.add(new Item(ff.getName(), num_item, date_modify, ff.getAbsolutePath(), isXashDir ? R.drawable.ic_launcher : R.drawable.folder ));
}
}
Collections.sort(dir);
if(folder.getPath().length() > 1)
dir.add(0, new Item( "..", getString(R.string.parent_directory), "", folder.getParent(), R.drawable.folder));
return dir;
}
protected void onPostExecute(List<Item> dir)
{
setTitle(getString(R.string.current_dir) + " " +folder.getName());
adapter = new FileArrayAdapter(FPicker.this,R.layout.row,dir);
delta = (ListView)findViewById(R.id.FileView);
delta.setAdapter(adapter);
delta.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent , View v, int position, long id)
{
Item o = adapter.getItem(position);
currentDir = new File(o.getPath());
fill(currentDir);
}
});
FPicker.mSelectBtn.setEnabled( true );
}
}
public void onFileClick(View v)
{
Toast.makeText(this, getString(R.string.chosen_path) + " " + currentDir, Toast.LENGTH_SHORT).show();
Intent intent = new Intent();
intent.putExtra("GetPath",currentDir.toString());
setResult(RESULT_OK, intent);
finish();
}
}
class FileArrayAdapter extends ArrayAdapter<Item>
{
private Context c;
private int id;
private List<Item>items;
public FileArrayAdapter(Context context, int textViewResourceId, List<Item> objects)
{
super(context, textViewResourceId, objects);
c = context;
id = textViewResourceId;
items = objects;
}
public Item getItem(int i)
{
return items.get(i);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null)
{
LayoutInflater vi = (LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(id, null);
}
final Item finstance = items.get(position);
if (finstance != null)
{
TextView filename = (TextView) v.findViewById(R.id.filename);
TextView fileitems = (TextView) v.findViewById(R.id.fileitems);
TextView filedate = (TextView) v.findViewById(R.id.filedate);
ImageView imageicon = (ImageView) v.findViewById(R.id.fd_Icon1);
Drawable image = c.getResources().getDrawable(finstance.getImage());
imageicon.setImageDrawable(image);
if(filename!=null)
filename.setText(finstance.getName());
if(fileitems!=null)
fileitems.setText(finstance.getData());
if(filedate!=null)
filedate.setText(finstance.getDate());
}
return v;
}
}
class Item implements Comparable<Item>
{
private String name;
private String data;
private String date;
private String path;
private int image;
public Item(String n,String d, String dt, String p, int img)
{
name = n;
data = d;
date = dt;
path = p;
image = img;
}
public String getName()
{
return name;
}
public String getData()
{
return data;
}
public String getDate()
{
return date;
}
public String getPath()
{
return path;
}
public int getImage()
{
return image;
}
public int compareTo(Item o)
{
if(this.name != null)
return this.name.toLowerCase().compareTo(o.getName().toLowerCase());
else
throw new IllegalArgumentException();
}
}
@@ -0,0 +1,51 @@
package in.celest.xash3d;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import java.io.FileOutputStream;
import java.io.InputStream;
import android.content.SharedPreferences;
public class InstallReceiver extends BroadcastReceiver {
private static final String TAG = "XASH3D";
@Override
public void onReceive(Context context, Intent arg1) {
String pkgname = arg1.getData().getEncodedSchemeSpecificPart();
Log.d( TAG, "Install received, package " + pkgname );
if( context.getPackageName().equals(pkgname) )
extractPAK(context, true);
}
public static SharedPreferences mPref = null;
private static final int PAK_VERSION = 7;
public static synchronized void extractPAK(Context context, Boolean force) {
InputStream is = null;
FileOutputStream os = null;
try {
if( mPref == null )
mPref = context.getSharedPreferences("engine", 0);
synchronized( mPref )
{
if( mPref.getInt( "pakversion", 0 ) == PAK_VERSION && !force )
return;
String path = context.getFilesDir().getPath()+"/extras.pak";
is = context.getAssets().open("extras.pak");
os = new FileOutputStream(path);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
os.close();
is.close();
SharedPreferences.Editor editor = mPref.edit();
editor.putInt( "pakversion", PAK_VERSION );
editor.commit();
}
} catch( Exception e )
{
Log.e( TAG, "Failed to extract PAK:" + e.toString() );
}
}
}
@@ -0,0 +1,540 @@
package in.celest.xash3d;
import android.app.*;
import android.content.*;
import android.graphics.*;
import android.graphics.drawable.*;
import android.net.*;
import android.os.*;
import android.text.*;
import android.text.method.*;
import android.text.style.*;
import android.util.*;
import android.view.*;
import android.widget.*;
import in.celest.xash3d.hl.*;
import java.io.*;
import java.net.*;
import org.json.*;
import android.preference.*;
import su.xash.fwgslib.*;
public class LauncherActivity extends Activity
{
// public final static String ARGV = "in.celest.xash3d.MESSAGE";
public final static int sdk = FWGSLib.sdk;
public final static String UPDATE_LINK = "https://api.github.com/repos/FWGS/xash3d-android-project/releases"; // releases/latest doesn't return prerelease and drafts
static SharedPreferences mPref;
static EditText cmdArgs, resPath, writePath, resScale, resWidth, resHeight;
static ToggleButton useVolume, resizeWorkaround, useRoDir;
static CheckBox checkUpdates, immersiveMode, useRoDirAuto;
static TextView tvResPath, resResult;
static RadioButton radioScale, radioCustom;
static RadioGroup scaleGroup;
static CheckBox resolution;
static Spinner pixelSpinner;
static LinearLayout rodirSettings; // to easy show/hide
static int mEngineWidth, mEngineHeight;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
//super.setTheme( 0x01030005 );
if ( sdk >= 21 )
super.setTheme( 0x01030224 );
else super.setTheme( 0x01030005 );
if( sdk >= 8 && CertCheck.dumbAntiPDALifeCheck( this ) )
{
finish();
return;
}
setContentView(R.layout.activity_launcher);
TabHost tabHost = (TabHost) findViewById(R.id.tabhost);
tabHost.setup();
TabHost.TabSpec tabSpec;
tabSpec = tabHost.newTabSpec("tabtag1");
tabSpec.setIndicator(getString(R.string.text_tab1));
tabSpec.setContent(R.id.tab1);
tabHost.addTab(tabSpec);
tabSpec = tabHost.newTabSpec("tabtag2");
tabSpec.setIndicator(getString(R.string.text_tab2));
tabSpec.setContent(R.id.tab2);
tabHost.addTab(tabSpec);
if( sdk < 21 )
{
try
{
tabHost.invalidate();
for(int i = 0; i < tabHost.getTabWidget().getChildCount(); i++)
{
tabHost.getTabWidget().getChildAt(i).getBackground().setAlpha(255);
tabHost.getTabWidget().getChildAt(i).getLayoutParams().height = (int) (40 * getResources().getDisplayMetrics().density);
}
}
catch(Exception e){}
}
mPref = getSharedPreferences("engine", 0);
cmdArgs = (EditText) findViewById(R.id.cmdArgs);
useVolume = (ToggleButton) findViewById( R.id.useVolume );
resPath = (EditText) findViewById( R.id.cmd_path );
checkUpdates = (CheckBox)findViewById( R.id.check_updates );
//updateToBeta = (CheckBox)findViewById( R.id.check_betas );
pixelSpinner = (Spinner) findViewById( R.id.pixelSpinner );
resizeWorkaround = (ToggleButton) findViewById( R.id.enableResizeWorkaround );
tvResPath = (TextView) findViewById( R.id.textView_path );
immersiveMode = (CheckBox) findViewById( R.id.immersive_mode );
resolution = (CheckBox) findViewById(R.id.resolution);
resWidth = (EditText) findViewById(R.id.resolution_width);
resHeight = (EditText) findViewById(R.id.resolution_height);
resScale = (EditText) findViewById(R.id.resolution_scale);
radioCustom = (RadioButton) findViewById(R.id.resolution_custom_r);
radioScale = (RadioButton) findViewById(R.id.resolution_scale_r);
scaleGroup = (RadioGroup) findViewById( R.id.scale_group );
resResult = (TextView) findViewById( R.id.resolution_result );
writePath = (EditText) findViewById( R.id.cmd_path_rw );
useRoDir = (ToggleButton) findViewById( R.id.use_rodir );
useRoDirAuto = (CheckBox) findViewById( R.id.use_rodir_auto );
rodirSettings = (LinearLayout) findViewById( R.id.rodir_settings );
final String[] list = {
"32 bit (RGBA8888)",
"24 bit (RGB888)",
"16 bit (RGB565)",
"16 bit (RGBA5551)",
"16 bit (RGBA4444)",
"8 bit (RGB332)"
};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_dropdown_item, list);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
pixelSpinner.setAdapter(adapter);
Button selectFolderButton = ( Button ) findViewById( R.id.button_select );
selectFolderButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
selectFolder(v);
}
});
((Button)findViewById( R.id.button_launch )).setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
startXash(v);
}
});
((Button)findViewById( R.id.button_shortcut )).setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
createShortcut(v);
}
});
((Button)findViewById( R.id.button_about )).setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
aboutXash(v);
}
});
useVolume.setChecked(mPref.getBoolean("usevolume",true));
checkUpdates.setChecked(mPref.getBoolean("check_updates",true));
//updateToBeta.setChecked(mPref.getBoolean("check_betas", false));
updatePath(mPref.getString("basedir", FWGSLib.getDefaultXashPath() ) );
cmdArgs.setText(mPref.getString("argv","-dev 3 -log"));
pixelSpinner.setSelection(mPref.getInt("pixelformat", 0));
resizeWorkaround.setChecked(mPref.getBoolean("enableResizeWorkaround", true));
useRoDir.setChecked( mPref.getBoolean("use_rodir", false) );
useRoDirAuto.setChecked( mPref.getBoolean("use_rodir_auto", true) );
writePath.setText(mPref.getString("writedir", FWGSLib.getExternalFilesDir(this)));
resolution.setChecked( mPref.getBoolean("resolution_fixed", false ) );
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
// Swap resolution here, because engine is always(should be always) run in landscape mode
if( FWGSLib.isLandscapeOrientation( this ) )
{
mEngineWidth = metrics.widthPixels;
mEngineHeight = metrics.heightPixels;
}
else
{
mEngineWidth = metrics.heightPixels;
mEngineHeight = metrics.widthPixels;
}
resWidth.setText(String.valueOf(mPref.getInt("resolution_width", mEngineWidth )));
resHeight.setText(String.valueOf(mPref.getInt("resolution_height", mEngineHeight )));
resScale.setText(String.valueOf(mPref.getFloat("resolution_scale", 2.0f)));
resWidth.addTextChangedListener( resWidthTextChangeWatcher );
resHeight.addTextChangedListener( resTextChangeWatcher );
resScale.addTextChangedListener( resTextChangeWatcher );
if( mPref.getBoolean("resolution_custom", false) )
radioCustom.setChecked(true);
else radioScale.setChecked(true);
radioCustom.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged( CompoundButton v, boolean isChecked )
{
updateResolutionResult();
toggleResolutionFields();
}
} );
resolution.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged( CompoundButton v, boolean isChecked )
{
hideResolutionSettings( !isChecked );
}
});
useRoDir.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged( CompoundButton v, boolean isChecked )
{
hideRodirSettings( !isChecked );
}
});
if( sdk >= 19 )
{
immersiveMode.setChecked(mPref.getBoolean("immersive_mode", true));
}
else
{
immersiveMode.setVisibility(View.GONE); // not available
}
resPath.setOnFocusChangeListener( new View.OnFocusChangeListener()
{
@Override
public void onFocusChange(View v, boolean hasFocus)
{
updatePath( resPath.getText().toString() );
// I know what I am doing, so don't ask me about folder!
XashActivity.setFolderAsk( LauncherActivity.this, false );
}
} );
useRoDirAuto.setOnCheckedChangeListener( new CompoundButton.OnCheckedChangeListener()
{
@Override
public void onCheckedChanged( CompoundButton b, boolean isChecked )
{
if( isChecked )
{
writePath.setText( FWGSLib.getExternalFilesDir( LauncherActivity.this ) );
}
writePath.setEnabled( !isChecked );
}
});
// disable autoupdater for Google Play
if( !XashConfig.GP_VERSION && mPref.getBoolean("check_updates", true))
{
new CheckUpdate(getBaseContext(),true, false).execute(UPDATE_LINK);
}
FWGSLib.changeButtonsStyle((ViewGroup)tabHost.getParent());
hideResolutionSettings( !resolution.isChecked() );
hideRodirSettings( !useRoDir.isChecked() );
updateResolutionResult();
toggleResolutionFields();
if( !mPref.getBoolean("successfulRun",false) )
showFirstRun();
}
@Override
public void onResume()
{
super.onResume();
useRoDir.setChecked( mPref.getBoolean("use_rodir", false) );
useRoDirAuto.setChecked( mPref.getBoolean("use_rodir_auto", true) );
writePath.setText(mPref.getString("writedir", FWGSLib.getExternalFilesDir(this)));
hideRodirSettings( !useRoDir.isChecked() );
}
void updatePath( String text )
{
tvResPath.setText(getString(R.string.text_res_path) + ":\n" + text );
resPath.setText(text);
}
void hideResolutionSettings( boolean hide )
{
scaleGroup.setVisibility( hide ? View.GONE : View.VISIBLE );
}
void hideRodirSettings( boolean hide )
{
rodirSettings.setVisibility( hide ? View.GONE : View.VISIBLE );
}
TextWatcher resWidthTextChangeWatcher = new TextWatcher()
{
@Override
public void afterTextChanged(Editable s){}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after){}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
int h = (int)((float)mEngineHeight / mEngineWidth * getCustomEngineWidth());
resHeight.setText(String.valueOf(h));
updateResolutionResult();
}
};
TextWatcher resTextChangeWatcher = new TextWatcher()
{
@Override
public void afterTextChanged(Editable s){}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after){}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
updateResolutionResult();
}
};
void updateResolutionResult( )
{
int w, h;
if( radioCustom.isChecked() )
{
w = getCustomEngineWidth();
h = getCustomEngineHeight();
// some fool-proof
if( Math.abs((float)w/(float)h - 4.0/3.0) < 0.001 )
{
w = (int)((float)mEngineWidth / mEngineHeight * h+0.5);
resWidth.setText(String.valueOf(w));
}
}
else
{
final float scale = getResolutionScale();
w = (int)((float)mEngineWidth / scale);
h = (int)((float)mEngineHeight / scale);
}
resResult.setText( getString( R.string.resolution_result ) + w + "x" + h );
}
void toggleResolutionFields()
{
boolean isChecked = radioCustom.isChecked();
resWidth.setEnabled( isChecked );
resHeight.setEnabled( isChecked );
resScale.setEnabled( !isChecked );
}
float getResolutionScale()
{
return FWGSLib.atof( resScale.getText().toString(), 1.0f );
}
int getCustomEngineHeight()
{
return FWGSLib.atoi( resHeight.getText().toString(), mEngineHeight );
}
int getCustomEngineWidth()
{
return FWGSLib.atoi( resWidth.getText().toString(), mEngineWidth );
}
public void startXash(View view)
{
Intent intent = new Intent(this, XashActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
SharedPreferences.Editor editor = mPref.edit();
editor.putString("argv", cmdArgs.getText().toString());
editor.putBoolean("usevolume",useVolume.isChecked());
editor.putBoolean("use_rodir", useRoDir.isChecked() );
editor.putBoolean("use_rodir_auto", useRoDirAuto.isChecked() );
editor.putString("writedir", writePath.getText().toString());
editor.putString("basedir", resPath.getText().toString());
editor.putInt("pixelformat", pixelSpinner.getSelectedItemPosition());
editor.putBoolean("enableResizeWorkaround",resizeWorkaround.isChecked());
editor.putBoolean("check_updates", checkUpdates.isChecked());
editor.putBoolean("resolution_fixed", resolution.isChecked());
editor.putBoolean("resolution_custom", radioCustom.isChecked());
editor.putFloat("resolution_scale", getResolutionScale() );
editor.putInt("resolution_width", getCustomEngineWidth() );
editor.putInt("resolution_height", getCustomEngineHeight() );
if( sdk >= 19 )
editor.putBoolean("immersive_mode", immersiveMode.isChecked());
else
editor.putBoolean("immersive_mode", false); // just in case...
editor.commit();
startActivity(intent);
}
public void aboutXash(View view)
{
final Activity a = this;
this.runOnUiThread(new Runnable()
{
public void run()
{
final Dialog dialog = new Dialog(a);
dialog.setContentView(R.layout.about);
dialog.setCancelable(true);
dialog.show();
TextView tView6 = (TextView) dialog.findViewById(R.id.textView6);
tView6.setMovementMethod(LinkMovementMethod.getInstance());
((Button)dialog.findViewById( R.id.button_about_ok )).setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
dialog.cancel();
}
});
((Button)dialog.findViewById( R.id.show_firstrun )).setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
dialog.cancel();
Intent intent = new Intent(a, XashTutorialActivity.class);
startActivity(intent);
}
});
FWGSLib.changeButtonsStyle((ViewGroup)dialog.findViewById( R.id.show_firstrun ).getParent());
}
});
}
int m_iFirstRunCounter = 0;
public void showFirstRun()
{
startActivity(new Intent(this, in.celest.xash3d.XashTutorialActivity.class));
}
public static final int ID_SELECT_FOLDER = 42, ID_SELECT_RW_FOLDER = 43;
public void selectFolder(View view)
{
Intent intent = new Intent(this, in.celest.xash3d.FPicker.class);
startActivityForResult(intent, ID_SELECT_FOLDER);
resPath.setEnabled(false);
XashActivity.setFolderAsk( this, false );
}
public void selectRwFolder(View view)
{
Intent intent = new Intent(this, in.celest.xash3d.FPicker.class);
startActivityForResult(intent, ID_SELECT_RW_FOLDER);
writePath.setEnabled(false);
XashActivity.setFolderAsk( this, false );
}
public void onActivityResult(int requestCode, int resultCode, Intent resultData)
{
switch(requestCode)
{
case ID_SELECT_FOLDER:
{
if (resultCode == RESULT_OK)
{
try
{
if( resPath == null )
return;
updatePath(resultData.getStringExtra("GetPath"));
resPath.setEnabled( true );
}
catch(Exception e)
{
e.printStackTrace();
}
}
resPath.setEnabled(true);
break;
}
case ID_SELECT_RW_FOLDER:
{
if (resultCode == RESULT_OK)
{
try
{
if( writePath == null )
return;
writePath.setText(resultData.getStringExtra("GetPath"));
writePath.setEnabled( true );
}
catch(Exception e)
{
e.printStackTrace();
}
}
writePath.setEnabled(true);
break;
}
}
}
public void createShortcut(View view)
{
Intent intent = new Intent(this, ShortcutActivity.class);
intent.putExtra( "basedir", resPath.getText().toString() );
intent.putExtra( "name", "Xash3D" );
intent.putExtra( "argv", cmdArgs.getText().toString() );
startActivity(intent);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//getMenuInflater().inflate(R.menu.menu_launcher, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
/*if (id == R.id.action_settings) {
return true;
}*/
return super.onOptionsItemSelected(item);
}
}
@@ -0,0 +1,131 @@
package in.celest.xash3d;
import android.app.Activity;
import android.view.View;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.Toast;
import in.celest.xash3d.hl.R;
import android.widget.EditText;
import android.widget.Button;
import java.io.File;
import java.io.FilenameFilter;
import android.os.*;
public class ShortcutActivity extends Activity
{
static EditText name, gamedir, pkgname, argv;
String [] env = null;
public static final int sdk = Integer.valueOf(Build.VERSION.SDK);
@Override
protected void onCreate(Bundle bundle)
{
super.onCreate(bundle);
//material dialog
if ( sdk >= 21 )
super.setTheme( 0x01030225 );
else super.setTheme( 0x0103000b );
setContentView(R.layout.activity_shortcut);
Intent intent=getIntent();
name = (EditText)findViewById(R.id.shortcut_name);
pkgname = (EditText)findViewById(R.id.shortcut_pkgname);
gamedir = (EditText)findViewById(R.id.shortcut_gamedir);
argv = (EditText)findViewById(R.id.shortcut_cmdArgs);
((Button)findViewById( R.id.shortcut_buttonOk )).setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
saveShortcut(v);
}
});
String argvs = intent.getStringExtra("argv");
if( argvs != null )
argv.setText(argvs);
String pkgnames = intent.getStringExtra("pkgname");
if( pkgnames != null )
pkgname.setText(pkgnames);
String gamedirs = intent.getStringExtra("gamedir");
if( gamedirs != null )
gamedir.setText(gamedirs);
String names = intent.getStringExtra("name");
if( names != null )
name.setText(names);
env = intent.getStringArrayExtra("env");
//name.setText("Name");
}
public void saveShortcut(View view)
{
Intent intent = new Intent();
intent.setAction("in.celest.xash3d.START");
if(argv.length() != 0) intent.putExtra("argv",argv.getText().toString());
if(pkgname.length() != 0)
{
intent.putExtra("gamelibdir", "/data/data/"+pkgname.getText().toString().replace("!","in.celest.xash3d.")+"/lib/");
intent.putExtra("pakfile", "/data/data/"+pkgname.getText().toString().replace("!","in.celest.xash3d.")+"/files/extras.pak");
}
if(gamedir.length() != 0) intent.putExtra("gamedir",gamedir.getText().toString());
if(env != null)
intent.putExtra("env", env);
Intent wrapIntent = new Intent();
wrapIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, intent);
wrapIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name.getText().toString());
Bitmap icon = null;
// Try find icon
int size = (int) getResources().getDimension(android.R.dimen.app_icon_size);
String gamedirstring = getSharedPreferences("engine", 0).getString("basedir","/sdcard/xash/")+"/"+(gamedir.length()!=0?gamedir.getText().toString():"valve");
try
{
icon = Bitmap.createScaledBitmap(BitmapFactory.decodeFile(gamedirstring+"/icon.png"), size, size, false);
}
catch(Exception e)
{
}
if(icon == null) try
{
icon = Bitmap.createScaledBitmap(BitmapFactory.decodeFile(gamedirstring+"/game.ico"), size, size, false);
}
catch(Exception e)
{
}
if(icon == null) try
{
FilenameFilter icoFilter = new FilenameFilter() {
public boolean accept(File dir, String name) {
if(name.endsWith(".ico") || name.endsWith(".ICO")) {
return true;
}
return false;
}
};
File gamedirfile = new File(gamedirstring);
String files[] = gamedirfile.list(icoFilter);
icon = Bitmap.createScaledBitmap(BitmapFactory.decodeFile(gamedirstring+"/"+files[0]), size, size, false);
}
catch(Exception e)
{
// Android may not support ico loading, so fallback if something going wrong
icon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
}
wrapIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
if(getIntent().getAction() == "android.intent.action.CREATE_SHORTCUT" ) // Called from launcher
{
setResult(RESULT_OK, wrapIntent);
finish();
}
else try
{
wrapIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
getApplicationContext().sendBroadcast(wrapIntent);
Toast.makeText(getApplicationContext(), "Shortcut created!", Toast.LENGTH_SHORT).show();
}
catch(Exception e)
{
Toast.makeText(getApplicationContext(), "Problem creating shortcut: " + e.toString() +
"\nTry create it manually from laucnher", Toast.LENGTH_LONG).show();
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,7 @@
package in.celest.xash3d;
public class XashConfig {
public static final boolean PKG_TEST = false;
public static final boolean CHECK_SIGNATURES = false;
public static final boolean RELEASE = false;
public static final boolean GP_VERSION = false;
}
@@ -0,0 +1,125 @@
package in.celest.xash3d;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.*;
import android.app.*;
import android.content.*;
import android.view.*;
import android.os.*;
import android.util.*;
import android.graphics.*;
import android.text.method.*;
import android.text.*;
import android.media.*;
import android.hardware.*;
import android.content.*;
import android.widget.*;
import android.content.pm.*;
import android.net.Uri;
import android.provider.*;
import android.database.*;
import android.view.inputmethod.*;
import java.lang.*;
import java.util.List;
import java.security.MessageDigest;
import in.celest.xash3d.hl.R;
import in.celest.xash3d.XashConfig;
import in.celest.xash3d.JoystickHandler;
public class XashService extends Service
{
public static Notification notification;
public static int status_image = R.id.status_image;
public static int status_text = R.id.status_text;
@Override
public IBinder onBind(Intent intent)
{
return null;
}
public static class exitButtonListener extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
XashActivity.mEngineReady = false;
XashActivity.nativeUnPause();
XashActivity.nativeOnDestroy();
if( XashActivity.mSurface != null )
XashActivity.mSurface.engineThreadJoin();
System.exit(0);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
int status_exit_button = R.id.status_exit_button;
int notify = R.layout.notify;
if( XashActivity.sdk >= 21 )
{
status_image = R.id.status_image_21;
status_text = R.id.status_text_21;
status_exit_button = R.id.status_exit_button_21;
notify = R.layout.notify_21;
}
Log.d("XashService", "Service Started");
Intent engineIntent = new Intent(this, XashActivity.class);
engineIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
Intent exitIntent = new Intent(this, exitButtonListener.class);
final PendingIntent pendingExitIntent = PendingIntent.getBroadcast(this, 0, exitIntent, 0);
notification = new Notification(R.drawable.ic_statusbar, "Xash3D", System.currentTimeMillis());
notification.contentView = new RemoteViews(getApplicationContext().getPackageName(), notify);
notification.contentView.setTextViewText(status_text, "Xash3D Engine");
notification.contentView.setOnClickPendingIntent(status_exit_button, pendingExitIntent);
notification.contentIntent = PendingIntent.getActivity(getApplicationContext(), 0, engineIntent, 0);
notification.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE;
startForeground(100, notification);
return START_NOT_STICKY;
}
@Override
public void onDestroy()
{
super.onDestroy();
Log.d("XashService", "Service Destroyed");
}
@Override
public void onCreate()
{
}
@Override
public void onTaskRemoved(Intent rootIntent)
{
Log.e("XashService", "OnTaskRemoved");
//if( XashActivity.mEngineReady )
{
XashActivity.mEngineReady = false;
XashActivity.nativeUnPause();
XashActivity.nativeOnDestroy();
if( XashActivity.mSurface != null )
XashActivity.mSurface.engineThreadJoin();
System.exit(0);
}
stopSelf();
}
};
@@ -0,0 +1,219 @@
package in.celest.xash3d;
import android.animation.*;
import android.app.*;
import android.content.*;
import android.os.*;
import android.util.*;
import android.view.*;
import android.view.View.*;
import android.widget.*;
import android.widget.TableRow.*;
import in.celest.xash3d.hl.*;
import java.util.*;
import su.xash.fwgslib.*;
import android.view.View.MeasureSpec;
public class XashTutorialActivity extends Activity implements View.OnClickListener
{
private Button next, prev;
private LinearLayout indicatorLayout;
private FrameLayout containerLayout;
private RelativeLayout buttonContainer;
private int currentItem;
private int prevText, nextText, finishText, cancelText, numPages;
PagedView scroll;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if( FWGSLib.sdk >= 21 ) // material
setTheme(0x0103022e); // Theme_Material_NoActionBar
else
setTheme(0x01030006); // Theme_NoTitleBar
setContentView(R.layout.activity_tutorial);
initTexts();
initViews();
initPages();
changeFragment(0);
}
private void initTexts() {
prevText = R.string.prev;
cancelText = R.string.skip;
finishText = R.string.finish;
nextText = R.string.next;
}
private void initPages() {
LayoutInflater inflater;
inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup container = (ViewGroup)findViewById(R.id.container);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
scroll = new PagedView(this,metrics.widthPixels);
container.addView(scroll);
while( true )
{
int titleres = getResources().getIdentifier("page_title" + String.valueOf(numPages), "string", getPackageName());
if( titleres == 0 )
break;
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.tutorial_step , null);
TextView title = (TextView) layout.findViewById(R.id.title);
TextView text = (TextView) layout.findViewById(R.id.content);
ImageView drawable = (ImageView) layout.findViewById(R.id.image);
int contentres = getResources().getIdentifier("page_content" + String.valueOf(numPages), "string", getPackageName());
int drawableres = getResources().getIdentifier("page" + String.valueOf(numPages), "drawable", getPackageName());
if( drawableres == 0)
drawableres = getResources().getIdentifier("page" + String.valueOf(numPages) + "_" + Locale.getDefault().getLanguage(), "drawable", getPackageName());
if( drawableres == 0 )
drawableres = getResources().getIdentifier("page" + String.valueOf(numPages) + "_en", "drawable", getPackageName());
title.setText(titleres);
text.setText(contentres);
if( FWGSLib.isLandscapeOrientation(this) )
drawable.setScaleType(ImageView.ScaleType.FIT_CENTER);
drawable.setImageResource(drawableres);
scroll.addPage(layout);
numPages++;
}
scroll.setOnPageListener(new PagedView.OnPageListener(){
@Override
public void onPage(int page)
{
currentItem = page;
controlPosition();
}
});
if( FWGSLib.sdk < 14 ) // pre-ics does not apply buttons background
FWGSLib.changeButtonsStyle((ViewGroup)container.getParent());
}
private void controlPosition()
{
if( currentItem > numPages - 1 )
currentItem = numPages - 1;
notifyIndicator();
if (currentItem == numPages - 1) {
next.setText(finishText);
prev.setText(prevText);
} else if ( currentItem == 0) {
prev.setText(cancelText);
next.setText(nextText);
} else {
prev.setText(prevText);
next.setText(nextText);
}
}
private void initViews() {
currentItem = 0;
next = (Button) findViewById(R.id.next);
prev = (Button) findViewById(R.id.prev);
indicatorLayout = (LinearLayout) findViewById(R.id.indicatorLayout);
containerLayout = (FrameLayout) findViewById(R.id.containerLayout);
buttonContainer = (RelativeLayout) findViewById(R.id.buttonContainer);
next.setOnClickListener(this);
prev.setOnClickListener(this);
}
public void notifyIndicator() {
if (indicatorLayout.getChildCount() > 0)
indicatorLayout.removeAllViews();
for (int i = 0; i < 5; i++) {
ImageView imageView = new ImageView(this);
imageView.setPadding(8, 8, 8, 8);
int drawable = R.drawable.circle_black;
if (i == currentItem)
drawable = R.drawable.circle_white;
imageView.setImageResource(drawable);
final int finalI = i;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeFragment(finalI);
}
});
indicatorLayout.addView(imageView);
}
}
@Override
public void onBackPressed() {
if (currentItem == 0) {
finish();
} else {
changeFragment(false);
}
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.next) {
if( currentItem == numPages - 1 )
{
finish();
return;
}
changeFragment(true);
} else if (v.getId() == R.id.prev) {
if( currentItem == 0 )
{
finish();
return;
}
changeFragment(false);
}
}
private void changeFragment(int position) {
scroll.changePage(position);
}
private void changeFragment(boolean isNext) {
if (isNext) {
scroll.changePage(currentItem+1);
} else {
scroll.changePage(currentItem-1);
}
}
public void setPrevText(int text) {
prevText = text;
}
public void setNextText(int text) {
nextText = text;
}
public void setFinishText(int text) {
finishText = text;
}
public void setCancelText(int text) {
cancelText = text;
}
}
+101
View File
@@ -0,0 +1,101 @@
package su.xash.fwgslib;
import android.content.*;
import android.view.*;
import android.os.*;
import android.util.*;
import android.graphics.*;
import android.text.method.*;
import android.text.*;
import android.media.*;
import android.hardware.*;
import android.content.*;
import android.widget.*;
import android.content.pm.*;
import java.lang.*;
import java.util.List;
import java.security.MessageDigest;
import in.celest.xash3d.XashConfig; // change pkgname if needed
import in.celest.xash3d.hl.BuildConfig; // change pkgname if needed
public class CertCheck
{
// Certificate checking
private static String SIG = "DMsE8f5hlR7211D8uehbFpbA0n8=";
private static String SIG_TEST = ""; // a1ba: mittorn, add your signature later
private static String TAG = "XASH3D:CertCheck";
public static boolean dumbAntiPDALifeCheck( Context context )
{
if( !XashConfig.CHECK_SIGNATURES || BuildConfig.DEBUG )
return false; // disable checking for debug builds
final String sig;
if( XashConfig.PKG_TEST )
{
sig = SIG_TEST;
}
else
{
sig = SIG;
}
if( dumbCertificateCheck( context, context.getPackageName(), sig, false ) )
{
Log.e(TAG, "Please, don't resign our public release builds!");
Log.e(TAG, "If you want to insert some features, rebuild package with ANOTHER package name from git repository.");
return true;
}
return false;
}
public static boolean dumbCertificateCheck( Context context, String pkgName, String sig, boolean failIfNoPkg )
{
if( sig == null )
sig = SIG;
Log.d( TAG, "pkgName = " + pkgName );
try
{
PackageInfo info = context.getPackageManager()
.getPackageInfo( pkgName, PackageManager.GET_SIGNATURES );
for( Signature signature: info.signatures )
{
Log.d( TAG, "found signature" );
MessageDigest md = MessageDigest.getInstance( "SHA" );
final byte[] signatureBytes = signature.toByteArray();
md.update( signatureBytes );
final String curSIG = Base64.encodeToString( md.digest(), Base64.NO_WRAP );
if( sig.equals(curSIG) )
{
Log.d( TAG, "Found valid cert" );
return false;
}
}
}
catch( PackageManager.NameNotFoundException e )
{
Log.d( TAG, "Package not found" );
e.printStackTrace();
if( !failIfNoPkg )
return false;
}
catch( Exception e )
{
e.printStackTrace();
}
return true;
}
}
@@ -0,0 +1,142 @@
package su.xash.fwgslib;
import android.app.*;
import android.content.*;
import android.net.*;
import android.os.*;
import android.util.*;
import android.widget.*;
import in.celest.xash3d.hl.*;
import java.io.*;
import java.net.*;
import org.json.*;
public class CheckUpdate extends AsyncTask<String, Void, String> {
InputStream is = null;
ByteArrayOutputStream os = null;
boolean mSilent;
boolean mBeta;
Context mContext;
public CheckUpdate( Context context, boolean silent, boolean beta )
{
mSilent = silent;
mBeta = beta;
mContext = context;
}
protected String doInBackground(String... urls)
{
try
{
URL url = new URL(urls[0]);
is = url.openConnection().getInputStream();
os = new ByteArrayOutputStream();
byte[] buffer = new byte[8196];
int len;
while ((len = is.read(buffer)) > 0)
{
os.write(buffer, 0, len);
}
os.flush();
return os.toString();
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
}
protected void onPostExecute(String result)
{
JSONArray releases = null;
try
{
if (is != null)
{
is.close();
is = null;
}
}
catch(Exception e)
{
e.printStackTrace();
}
try
{
if (os != null)
{
releases = new JSONArray(os.toString());
os.close();
os = null;
}
}
catch(Exception e)
{
e.printStackTrace();
return;
}
if( releases == null )
return;
for( int i = 0; i < releases.length(); i++ )
{
final JSONObject obj;
try
{
obj = releases.getJSONObject(i);
final String version, url, name;
final boolean beta = obj.getBoolean("prerelease");
if( beta && !mBeta )
continue;
version = obj.getString("tag_name");
url = obj.getString("html_url");
name = obj.getString("name");
Log.d("Xash", "Found: " + version +
", I: " + mContext.getString(R.string.version_string));
// this is an update
if( mContext.getString(R.string.version_string).compareTo(version) < 0 )
{
String dialog_message = String.format(mContext.getString(R.string.update_message), name);
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setMessage(dialog_message)
.setPositiveButton(R.string.update, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
final Intent intent = new Intent(Intent.ACTION_VIEW).setData(Uri.parse(url));
mContext.startActivity(intent);
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener()
{ public void onClick(DialogInterface dialog, int id) {} } );
builder.create().show();
}
else if( !mSilent )
{
Toast.makeText(mContext, R.string.no_updates, Toast.LENGTH_SHORT).show();
}
// No need to check other releases, so we will stop here.
break;
}
catch(Exception e)
{
e.printStackTrace();
continue;
}
}
}
}
+231
View File
@@ -0,0 +1,231 @@
package su.xash.fwgslib;
import android.app.*;
import android.content.*;
import android.graphics.*;
import android.graphics.drawable.*;
import android.net.*;
import android.os.*;
import android.text.*;
import android.text.method.*;
import android.text.style.*;
import android.util.*;
import android.view.*;
import android.widget.*;
import java.io.*;
import java.net.*;
import org.json.*;
import android.preference.*;
/*
* This utility class is intended to hide some Android and Java design-flaws and
* also just shortcuts
*/
public class FWGSLib
{
private static final String TAG = "FWGSLib";
static String externalFilesDir;
public static boolean FBitSet( final int bits, final int mask )
{
return ((bits & mask) != 0);
}
public static boolean FExactBitSet( final int bits, final int mask )
{
return ((bits & mask) == mask );
}
public static float atof( String str, float fallback )
{
float ret;
try
{
ret = Float.valueOf( str );
}
catch( Exception e )
{
ret = fallback;
}
return ret;
}
public static int atoi( String str, int fallback )
{
int ret;
try
{
ret = Integer.valueOf( str );
}
catch( Exception e )
{
ret = fallback;
}
return ret;
}
public static boolean checkGameLibDir( String gamelibdir, String allowed )
{
try
{
Log.d( TAG, " gamelibdir = " + gamelibdir + " allowed = " + allowed );
if( gamelibdir.contains( "/.." ))
return false;
File f = new File( gamelibdir );
if( !f.isDirectory() )
{
Log.d( TAG, "Not a directory" );
return false;
}
if( !f.exists() )
{
Log.d( TAG, "Does not exist" );
return false;
}
// add trailing / for simple regexp
if( gamelibdir.charAt(gamelibdir.length() - 1) != '/' )
gamelibdir = gamelibdir + "/";
final String regex = ".+\\/" + allowed.replace(".", "\\.") + "(|(-\\d))\\/(.+|)";
Log.d( TAG, regex );
final boolean ret = gamelibdir.matches( regex );
Log.d( TAG, "ret = " + ret );
return ret;
}
catch( Exception e )
{
e.printStackTrace();
}
return false;
}
public static String getDefaultXashPath()
{
File dir = Environment.getExternalStorageDirectory();
if( dir != null && dir.exists() )
return dir.getPath() + "/xash";
return "/sdcard/xash";
}
static class GetExternalFilesDir extends Thread
{
Context ctx;
GetExternalFilesDir( Context ctx1 )
{
ctx = ctx1;
}
@Override
public void run()
{
try
{
File f = ctx.getExternalFilesDir(null);
f.mkdirs();
externalFilesDir = f.getAbsolutePath();
Log.d(TAG, "getExternalFilesDir success");
}
catch( Exception e )
{
Log.e( TAG, e.toString(), e);
}
}
}
public static String getExternalFilesDir( Context ctx )
{
if( externalFilesDir != null )
return externalFilesDir;
try
{
if( sdk >= 8 )
{
Thread t = new GetExternalFilesDir(ctx);
t.start();
t.join(2000);
}
}
catch(Exception e)
{
Log.e( TAG, e.toString(), e);
externalFilesDir = getDefaultXashPath();
}
if( externalFilesDir == null )
externalFilesDir = getDefaultXashPath();
return externalFilesDir;
}
public static boolean isLandscapeOrientation( Activity act )
{
DisplayMetrics metrics = new DisplayMetrics();
act.getWindowManager().getDefaultDisplay().getMetrics(metrics);
return (metrics.widthPixels > metrics.heightPixels);
}
public static String getStringExtraFromIntent( Intent intent, String extraString, String ifNotFound )
{
String ret = intent.getStringExtra( extraString );
if( ret == null )
{
ret = ifNotFound;
}
return ret;
}
public static void changeButtonsStyle( ViewGroup parent )
{
if( sdk >= 21 )
return;
for( int i = parent.getChildCount() - 1; i >= 0; i-- )
{
try
{
final View child = parent.getChildAt(i);
if( child == null )
continue;
if( child instanceof ViewGroup )
{
changeButtonsStyle((ViewGroup) child);
// DO SOMETHING WITH VIEWGROUP, AFTER CHILDREN HAS BEEN LOOPED
}
else if( child instanceof Button )
{
final Button b = (Button)child;
final Drawable bg = b.getBackground();
if(bg!= null)bg.setAlpha( 96 );
b.setTextColor( 0xFFFFFFFF );
b.setTextSize( 15f );
//b.setText(b.getText().toString().toUpperCase());
b.setTypeface( b.getTypeface(),Typeface.BOLD );
}
else if( child instanceof EditText )
{
final EditText b = ( EditText )child;
b.setBackgroundColor( 0xFF353535 );
b.setTextColor( 0xFFFFFFFF );
b.setTextSize( 15f );
}
}
catch( Exception e )
{
}
}
}
public static final int sdk = Integer.valueOf(Build.VERSION.SDK);
}
+137
View File
@@ -0,0 +1,137 @@
package su.xash.fwgslib;
import android.view.*;
import android.view.View.*;
import android.widget.*;
import android.content.Context;
public class PagedView extends HorizontalScrollView
{
boolean isDelayed, isInc, anim;
int lastScroll, pageWidth, currentPage, numPages, targetPage;
float firstx,lastx;
LinearLayout pageContainer;
ViewGroup.LayoutParams pageParams;
// allow detect animation end
public static abstract class OnPageListener
{
abstract public void onPage(int page);
}
OnPageListener listener;
public PagedView(Context ctx, int pagewidth)
{
super(ctx);
pageContainer = new LinearLayout(ctx);
pageContainer.setOrientation(LinearLayout.HORIZONTAL);
setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT));
setScrollBarStyle(SCROLLBARS_INSIDE_INSET);
addView(pageContainer);
pageWidth = pagewidth;
// this will be applied to every page
pageParams = new ViewGroup.LayoutParams(pagewidth, LayoutParams.FILL_PARENT);
}
private void animateScroll()
{
if( !anim )
{
// allow only correct position if anim disabled
scrollTo(pageWidth*currentPage,0);
return;
}
if( isInc && lastScroll >= pageWidth * targetPage || !isInc && lastScroll <= pageWidth * targetPage )
{
// got target page, stop now
anim = false;
currentPage = targetPage;
scrollTo(pageWidth*targetPage,0);
if( listener != null )
listener.onPage(currentPage);
return;
}
if( !isDelayed ) //semaphore
{
isDelayed = true;
postDelayed(new Runnable()
{
public void run()
{
isDelayed = false;
// animate to 1/50 of page every 10 ms
scrollBy(isInc?pageWidth/50:-pageWidth/50,0);
}
},10);
}
}
// add view and set layout
public void addPage(View view)
{
view.setLayoutParams(pageParams);
pageContainer.addView(view);
numPages++;
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt)
{
// this called on every scrollTo/scrollBy and touch scroll
super.onScrollChanged(l,t,oldl,oldt);
lastScroll=l;
isInc = l>oldl;
animateScroll();
}
@Override
public boolean onTouchEvent(MotionEvent e)
{
switch( e.getAction() )
{
case MotionEvent.ACTION_DOWN:
// store swipe start
lastx = firstx = e.getX();
// animation will be started on next scroll event
anim = true;
break;
case MotionEvent.ACTION_MOVE:
// animation will start in supercall, so select direction now
isInc = e.getX() < lastx;
targetPage = isInc?currentPage+1:currentPage-1;
lastx = e.getX();
break;
case MotionEvent.ACTION_UP:
// detect misstouch (<100 pixels)
if( Math.abs(e.getX()-firstx) < 100)
{
/*
anim = false;
targetPage = currentPage;
scrollTo(currentPage*pageWidth,0);*/
targetPage = currentPage;
isInc = currentPage * pageWidth > lastScroll;
}
return false;
}
return super.onTouchEvent(e);
}
// set page number
public void changePage(int page)
{
targetPage = page;
anim = true;
isInc = targetPage > currentPage;
animateScroll();
}
// call when animation ends
public void setOnPageListener(OnPageListener listener1)
{
listener = listener1;
}
}