Merge pull request #2389 from sigmabeta/lollipop-ui-tweaks
Android: Add file browser screen to new UI, and several tweaks.
@ -56,5 +56,5 @@ dependencies {
|
||||
compile 'de.hdodenhof:circleimageview:1.2.2'
|
||||
|
||||
// For loading huge screenshots from the disk.
|
||||
compile "com.squareup.picasso:picasso:2.4.0"
|
||||
compile 'com.squareup.picasso:picasso:2.5.2'
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
<activity
|
||||
android:name=".activities.GameGridActivity"
|
||||
android:label="Dolphin New UI"
|
||||
android:theme="@style/DolphinWii">
|
||||
android:theme="@style/DolphinGamecube">
|
||||
|
||||
<!-- This intentfilter marks this Activity as the one that gets launched from Home screen. -->
|
||||
<intent-filter>
|
||||
@ -25,6 +25,11 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activities.AddDirectoryActivity"
|
||||
android:theme="@style/DolphinWii"
|
||||
android:label="@string/add_directory_title"/>
|
||||
|
||||
<activity
|
||||
android:name="org.dolphinemu.dolphinemu.gamelist.GameListActivity"
|
||||
android:label="@string/app_name"
|
||||
|
@ -0,0 +1,112 @@
|
||||
package org.dolphinemu.dolphinemu.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import org.dolphinemu.dolphinemu.BuildConfig;
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.adapters.FileAdapter;
|
||||
|
||||
/**
|
||||
* An Activity that shows a list of files and folders, allowing the user to tell the app which folder(s)
|
||||
* contains the user's games.
|
||||
*/
|
||||
public class AddDirectoryActivity extends Activity implements FileAdapter.FileClickListener
|
||||
{
|
||||
public static final String KEY_CURRENT_PATH = BuildConfig.APPLICATION_ID + ".path";
|
||||
|
||||
private FileAdapter mAdapter;
|
||||
private Toolbar mToolbar;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_add_directory);
|
||||
|
||||
mToolbar = (Toolbar) findViewById(R.id.toolbar_folder_list);
|
||||
setActionBar(mToolbar);
|
||||
|
||||
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list_files);
|
||||
|
||||
// Specifying the LayoutManager determines how the RecyclerView arranges views.
|
||||
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
|
||||
String path;
|
||||
// Stuff in this block only happens when this activity is newly created (i.e. not a rotation)
|
||||
if (savedInstanceState == null)
|
||||
{
|
||||
path = Environment.getExternalStorageDirectory().getPath();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the path we were looking at before we rotated.
|
||||
path = savedInstanceState.getString(KEY_CURRENT_PATH);
|
||||
}
|
||||
|
||||
mAdapter = new FileAdapter(path, this);
|
||||
recyclerView.setAdapter(mAdapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_add_directory, menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item)
|
||||
{
|
||||
switch (item.getItemId())
|
||||
{
|
||||
case R.id.menu_up_one_level:
|
||||
mAdapter.upOneLevel();
|
||||
break;
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState)
|
||||
{
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
// Save the path we're looking at so when rotation is done, we start from same folder.
|
||||
outState.putString(KEY_CURRENT_PATH, mAdapter.getPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the GameGridActivity that launched this Activity that the user picked a folder.
|
||||
*/
|
||||
@Override
|
||||
public void finishSuccessfully()
|
||||
{
|
||||
Intent resultData = new Intent();
|
||||
|
||||
resultData.putExtra(KEY_CURRENT_PATH, mAdapter.getPath());
|
||||
setResult(RESULT_OK, resultData);
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSubtitle(String path)
|
||||
{
|
||||
mToolbar.setSubtitle(path);
|
||||
}
|
||||
}
|
@ -2,13 +2,16 @@ package org.dolphinemu.dolphinemu.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v7.widget.GridLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import org.dolphinemu.dolphinemu.AssetCopyService;
|
||||
@ -24,11 +27,15 @@ import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class GameGridActivity extends Activity
|
||||
/**
|
||||
* The main Activity of the Lollipop style UI. Shows a grid of games on tablets & landscape phones,
|
||||
* shows a list of games on portrait phones.
|
||||
*/
|
||||
public final class GameGridActivity extends Activity
|
||||
{
|
||||
private RecyclerView mRecyclerView;
|
||||
private RecyclerView.Adapter mAdapter;
|
||||
private RecyclerView.LayoutManager mLayoutManager;
|
||||
private static final int REQUEST_ADD_DIRECTORY = 1;
|
||||
|
||||
private GameAdapter mAdapter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
@ -39,21 +46,34 @@ public class GameGridActivity extends Activity
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_game_list);
|
||||
setActionBar(toolbar);
|
||||
|
||||
mRecyclerView = (RecyclerView) findViewById(R.id.grid_games);
|
||||
ImageButton buttonAddDirectory = (ImageButton) findViewById(R.id.button_add_directory);
|
||||
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.grid_games);
|
||||
|
||||
// use this setting to improve performance if you know that changes
|
||||
// in content do not change the layout size of the RecyclerView
|
||||
//mRecyclerView.setHasFixedSize(true);
|
||||
|
||||
// Specifying the LayoutManager determines how the RecyclerView arranges views.
|
||||
mLayoutManager = new GridLayoutManager(this, 4);
|
||||
mRecyclerView.setLayoutManager(mLayoutManager);
|
||||
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(this, 4);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
|
||||
mRecyclerView.addItemDecoration(new GameAdapter.SpacesItemDecoration(8));
|
||||
recyclerView.addItemDecoration(new GameAdapter.SpacesItemDecoration(8));
|
||||
|
||||
// Create an adapter that will relate the dataset to the views on-screen.
|
||||
mAdapter = new GameAdapter(getGameList());
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
recyclerView.setAdapter(mAdapter);
|
||||
|
||||
buttonAddDirectory.setOnClickListener(new View.OnClickListener()
|
||||
{
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
Intent fileChooser = new Intent(GameGridActivity.this, AddDirectoryActivity.class);
|
||||
|
||||
// The second argument to this method is read below in onActivityResult().
|
||||
startActivityForResult(fileChooser, REQUEST_ADD_DIRECTORY);
|
||||
}
|
||||
});
|
||||
|
||||
// Stuff in this block only happens when this activity is newly created (i.e. not a rotation)
|
||||
if (savedInstanceState == null)
|
||||
@ -64,11 +84,46 @@ public class GameGridActivity extends Activity
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback from AddDirectoryActivity. Applies any changes necessary to the GameGridActivity.
|
||||
*
|
||||
* @param requestCode An int describing whether the Activity that is returning did so successfully.
|
||||
* @param resultCode An int describing what Activity is giving us this callback.
|
||||
* @param result The information the returning Activity is providing us.
|
||||
*/
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent result)
|
||||
{
|
||||
// If the user picked a file, as opposed to just backing out.
|
||||
if (resultCode == RESULT_OK)
|
||||
{
|
||||
// Sanity check to make sure the Activity that just returned was the AddDirectoryActivity;
|
||||
// other activities might use this callback in the future (don't forget to change Javadoc!)
|
||||
if (requestCode == REQUEST_ADD_DIRECTORY)
|
||||
{
|
||||
// Get the path the user selected in AddDirectoryActivity.
|
||||
String path = result.getStringExtra(AddDirectoryActivity.KEY_CURRENT_PATH);
|
||||
|
||||
// Store this path as a preference.
|
||||
// TODO Use SQLite instead.
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
|
||||
editor.putString(AddDirectoryActivity.KEY_CURRENT_PATH, path);
|
||||
|
||||
// Using commit, not apply, in order to block so the next method has the correct data to load.
|
||||
editor.commit();
|
||||
|
||||
mAdapter.setGameList(getGameList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.gamelist_menu, menu);
|
||||
inflater.inflate(R.menu.menu_game_grid, menu);
|
||||
return true;
|
||||
|
||||
}
|
||||
@ -82,48 +137,43 @@ public class GameGridActivity extends Activity
|
||||
|
||||
NativeLibrary.SetUserDirectory(DefaultDir);
|
||||
|
||||
String Directories = NativeLibrary.GetConfig("Dolphin.ini", "General", "ISOPaths", "0");
|
||||
Log.v("DolphinEmu", "Directories: " + Directories);
|
||||
int intDirectories = Integer.parseInt(Directories);
|
||||
|
||||
// Extensions to filter by.
|
||||
Set<String> exts = new HashSet<String>(Arrays.asList(".dff", ".dol", ".elf", ".gcm", ".gcz", ".iso", ".wad", ".wbfs"));
|
||||
|
||||
for (int a = 0; a < intDirectories; ++a)
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||
|
||||
String path = prefs.getString(AddDirectoryActivity.KEY_CURRENT_PATH, "/");
|
||||
|
||||
File currentDir = new File(path);
|
||||
File[] dirs = currentDir.listFiles();
|
||||
try
|
||||
{
|
||||
String BrowseDir = NativeLibrary.GetConfig("Dolphin.ini", "General", "ISOPath" + a, "");
|
||||
Log.v("DolphinEmu", "Directory " + a + ": " + BrowseDir);
|
||||
|
||||
File currentDir = new File(BrowseDir);
|
||||
File[] dirs = currentDir.listFiles();
|
||||
try
|
||||
for (File entry : dirs)
|
||||
{
|
||||
for (File entry : dirs)
|
||||
if (!entry.isHidden() && !entry.isDirectory())
|
||||
{
|
||||
if (!entry.isHidden() && !entry.isDirectory())
|
||||
String entryName = entry.getName();
|
||||
|
||||
// Check that the file has an appropriate extension before trying to read out of it.
|
||||
if (exts.contains(entryName.toLowerCase().substring(entryName.lastIndexOf('.'))))
|
||||
{
|
||||
String entryName = entry.getName();
|
||||
|
||||
// Check that the file has an appropriate extension before trying to read out of it.
|
||||
if (exts.contains(entryName.toLowerCase().substring(entryName.lastIndexOf('.'))))
|
||||
{
|
||||
GcGame game = new GcGame(NativeLibrary.GetTitle(entry.getAbsolutePath()),
|
||||
NativeLibrary.GetDescription(entry.getAbsolutePath()).replace("\n", " "),
|
||||
// TODO Some games might actually not be from this region, believe it or not.
|
||||
"United States",
|
||||
entry.getAbsolutePath(),
|
||||
NativeLibrary.GetGameId(entry.getAbsolutePath()),
|
||||
NativeLibrary.GetDate(entry.getAbsolutePath()));
|
||||
|
||||
gameList.add(game);
|
||||
}
|
||||
GcGame game = new GcGame(NativeLibrary.GetTitle(entry.getAbsolutePath()),
|
||||
NativeLibrary.GetDescription(entry.getAbsolutePath()).replace("\n", " "),
|
||||
// TODO Some games might actually not be from this region, believe it or not.
|
||||
"United States",
|
||||
entry.getAbsolutePath(),
|
||||
NativeLibrary.GetGameId(entry.getAbsolutePath()),
|
||||
NativeLibrary.GetDate(entry.getAbsolutePath()));
|
||||
|
||||
gameList.add(game);
|
||||
}
|
||||
|
||||
}
|
||||
} catch (Exception ignored)
|
||||
{
|
||||
|
||||
}
|
||||
} catch (Exception ignored)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return gameList;
|
||||
|
@ -0,0 +1,212 @@
|
||||
package org.dolphinemu.dolphinemu.adapters;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.model.FileListItem;
|
||||
import org.dolphinemu.dolphinemu.viewholders.FileViewHolder;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
public class FileAdapter extends RecyclerView.Adapter<FileViewHolder> implements View.OnClickListener
|
||||
{
|
||||
private ArrayList<FileListItem> mFileList;
|
||||
|
||||
private String mPath;
|
||||
|
||||
private FileClickListener mListener;
|
||||
|
||||
/**
|
||||
* Initializes the dataset to be displayed, and associates the Adapter with the
|
||||
* Activity as an event listener.
|
||||
*
|
||||
* @param path A String containing the path to the directory to be shown by this Adapter.
|
||||
* @param listener An Activity that can respond to callbacks from this Adapter.
|
||||
*/
|
||||
public FileAdapter(String path, FileClickListener listener)
|
||||
{
|
||||
mFileList = generateFileList(new File(path));
|
||||
mListener = listener;
|
||||
mListener.updateSubtitle(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the LayoutManager when it is necessary to create a new view.
|
||||
*
|
||||
* @param parent The RecyclerView (I think?) the created view will be thrown into.
|
||||
* @param viewType Not used here, but useful when more than one type of child will be used in the RecyclerView.
|
||||
* @return The created ViewHolder with references to all the child view's members.
|
||||
*/
|
||||
@Override
|
||||
public FileViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
|
||||
{
|
||||
// Create a new view.
|
||||
View listItem = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.list_item_file, parent, false);
|
||||
|
||||
listItem.setOnClickListener(this);
|
||||
|
||||
// Use that view to create a ViewHolder.
|
||||
return new FileViewHolder(listItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the LayoutManager when a new view is not necessary because we can recycle
|
||||
* an existing one (for example, if a view just scrolled onto the screen from the bottom, we
|
||||
* can use the view that just scrolled off the top instead of inflating a new one.)
|
||||
*
|
||||
* @param holder A ViewHolder representing the view we're recycling.
|
||||
* @param position The position of the 'new' view in the dataset.
|
||||
*/
|
||||
@Override
|
||||
public void onBindViewHolder(FileViewHolder holder, int position)
|
||||
{
|
||||
// Get a reference to the item from the dataset; we'll use this to fill in the view contents.
|
||||
final FileListItem file = mFileList.get(position);
|
||||
|
||||
// Fill in the view contents.
|
||||
switch (file.getType())
|
||||
{
|
||||
case FileListItem.TYPE_FOLDER:
|
||||
holder.imageType.setImageResource(R.drawable.ic_folder);
|
||||
break;
|
||||
|
||||
case FileListItem.TYPE_GC:
|
||||
holder.imageType.setImageResource(R.drawable.ic_gamecube);
|
||||
break;
|
||||
|
||||
case FileListItem.TYPE_WII:
|
||||
holder.imageType.setImageResource(R.drawable.ic_wii);
|
||||
break;
|
||||
|
||||
case FileListItem.TYPE_OTHER:
|
||||
holder.imageType.setImageResource(android.R.color.transparent);
|
||||
break;
|
||||
}
|
||||
|
||||
holder.textFileName.setText(file.getFilename());
|
||||
holder.itemView.setTag(file.getPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the LayoutManager to find out how much data we have.
|
||||
*
|
||||
* @return Size of the dataset.
|
||||
*/
|
||||
@Override
|
||||
public int getItemCount()
|
||||
{
|
||||
return mFileList.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* When a file is clicked, determine if it is a directory; if it is, show that new directory's
|
||||
* contents. If it is not, end the activity successfully.
|
||||
*
|
||||
* @param view The View representing the file the user clicked on.
|
||||
*/
|
||||
@Override
|
||||
public void onClick(final View view)
|
||||
{
|
||||
final String path = (String) view.getTag();
|
||||
|
||||
File clickedFile = new File(path);
|
||||
|
||||
if (clickedFile.isDirectory())
|
||||
{
|
||||
final ArrayList<FileListItem> fileList = generateFileList(clickedFile);
|
||||
|
||||
if (fileList.isEmpty())
|
||||
{
|
||||
Toast.makeText(view.getContext(), R.string.add_directory_empty_folder, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Delay the loading of the new directory to give a little bit of time for UI feedback
|
||||
// to happen. Hacky, but good enough for now; this is necessary because we're modifying
|
||||
// the RecyclerView's contents, rather than constructing a new one.
|
||||
view.getHandler().postDelayed(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mFileList = fileList;
|
||||
notifyDataSetChanged();
|
||||
mListener.updateSubtitle(path);
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Pass the activity the path of the parent directory of the clicked file.
|
||||
mListener.finishSuccessfully();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given directory, return a list of Files it contains.
|
||||
*
|
||||
* @param directory A File representing the directory that should have its contents displayed.
|
||||
* @return
|
||||
*/
|
||||
private ArrayList<FileListItem> generateFileList(File directory)
|
||||
{
|
||||
File[] children = directory.listFiles();
|
||||
ArrayList<FileListItem> fileList = new ArrayList<FileListItem>(children.length);
|
||||
|
||||
for (File child : children)
|
||||
{
|
||||
if (!child.isHidden())
|
||||
{
|
||||
FileListItem item = new FileListItem(child);
|
||||
fileList.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
mPath = directory.getAbsolutePath();
|
||||
|
||||
Collections.sort(fileList);
|
||||
return fileList;
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
|
||||
public void setPath(String path)
|
||||
{
|
||||
File directory = new File(path);
|
||||
|
||||
mFileList = generateFileList(directory);
|
||||
notifyDataSetChanged();
|
||||
mListener.updateSubtitle(path);
|
||||
}
|
||||
|
||||
public void upOneLevel()
|
||||
{
|
||||
File currentDirectory = new File(mPath);
|
||||
File parentDirectory = currentDirectory.getParentFile();
|
||||
|
||||
mFileList = generateFileList(parentDirectory);
|
||||
notifyDataSetChanged();
|
||||
mListener.updateSubtitle(mPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to the containing Activity.
|
||||
*/
|
||||
public interface FileClickListener
|
||||
{
|
||||
void finishSuccessfully();
|
||||
|
||||
void updateSubtitle(String path);
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package org.dolphinemu.dolphinemu.adapters;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
@ -9,12 +11,16 @@ import android.view.ViewGroup;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.dialogs.GameDetailsDialog;
|
||||
import org.dolphinemu.dolphinemu.emulation.EmulationActivity;
|
||||
import org.dolphinemu.dolphinemu.model.Game;
|
||||
import org.dolphinemu.dolphinemu.viewholders.GameViewHolder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GameAdapter extends RecyclerView.Adapter<GameViewHolder>
|
||||
public class GameAdapter extends RecyclerView.Adapter<GameViewHolder> implements
|
||||
View.OnClickListener,
|
||||
View.OnLongClickListener
|
||||
{
|
||||
private ArrayList<Game> mGameList;
|
||||
|
||||
@ -42,6 +48,9 @@ public class GameAdapter extends RecyclerView.Adapter<GameViewHolder>
|
||||
View gameCard = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.card_game, parent, false);
|
||||
|
||||
gameCard.setOnClickListener(this);
|
||||
gameCard.setOnLongClickListener(this);
|
||||
|
||||
// Use that view to create a ViewHolder.
|
||||
GameViewHolder holder = new GameViewHolder(gameCard);
|
||||
return holder;
|
||||
@ -64,6 +73,8 @@ public class GameAdapter extends RecyclerView.Adapter<GameViewHolder>
|
||||
// Fill in the view contents.
|
||||
Picasso.with(holder.imageScreenshot.getContext())
|
||||
.load(game.getScreenPath())
|
||||
.fit()
|
||||
.centerCrop()
|
||||
.error(R.drawable.no_banner)
|
||||
.into(holder.imageScreenshot);
|
||||
|
||||
@ -72,12 +83,10 @@ public class GameAdapter extends RecyclerView.Adapter<GameViewHolder>
|
||||
{
|
||||
holder.textDescription.setText(game.getDescription());
|
||||
}
|
||||
holder.buttonDetails.setTag(game.getGameId());
|
||||
|
||||
holder.path = game.getPath();
|
||||
holder.screenshotPath = game.getScreenPath();
|
||||
holder.game = game;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -91,6 +100,45 @@ public class GameAdapter extends RecyclerView.Adapter<GameViewHolder>
|
||||
return mGameList.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the game that was clicked on.
|
||||
*
|
||||
* @param view The card representing the game the user wants to play.
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
GameViewHolder holder = (GameViewHolder) view.getTag();
|
||||
|
||||
// Start the emulation activity and send the path of the clicked ISO to it.
|
||||
Intent intent = new Intent(view.getContext(), EmulationActivity.class);
|
||||
|
||||
intent.putExtra("SelectedGame", holder.path);
|
||||
|
||||
view.getContext().startActivity(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches the details activity for this Game, using an ID stored in the
|
||||
* details button's Tag.
|
||||
*
|
||||
* @param view The Card button that was long-clicked.
|
||||
*/
|
||||
@Override
|
||||
public boolean onLongClick(View view)
|
||||
{
|
||||
GameViewHolder holder = (GameViewHolder) view.getTag();
|
||||
|
||||
// Get the ID of the game we want to look at.
|
||||
// TODO This should be all we need to pass in, eventually.
|
||||
// String gameId = (String) holder.gameId;
|
||||
|
||||
Activity activity = (Activity) view.getContext();
|
||||
GameDetailsDialog.newInstance(holder.game).show(activity.getFragmentManager(), "game_details");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static class SpacesItemDecoration extends RecyclerView.ItemDecoration
|
||||
{
|
||||
private int space;
|
||||
@ -107,7 +155,12 @@ public class GameAdapter extends RecyclerView.Adapter<GameViewHolder>
|
||||
outRect.right = space;
|
||||
outRect.bottom = space;
|
||||
outRect.top = space;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void setGameList(ArrayList<Game> gameList)
|
||||
{
|
||||
mGameList = gameList;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,8 @@ public class GameDetailsDialog extends DialogFragment
|
||||
// Fill in the view contents.
|
||||
Picasso.with(imageGameScreen.getContext())
|
||||
.load(getArguments().getString(ARGUMENT_GAME_SCREENSHOT_PATH))
|
||||
.fit()
|
||||
.centerCrop()
|
||||
.noFade()
|
||||
.noPlaceholder()
|
||||
.into(imageGameScreen);
|
||||
|
@ -0,0 +1,85 @@
|
||||
package org.dolphinemu.dolphinemu.model;
|
||||
|
||||
|
||||
import org.dolphinemu.dolphinemu.NativeLibrary;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class FileListItem implements Comparable<FileListItem>
|
||||
{
|
||||
public static final int TYPE_FOLDER = 0;
|
||||
public static final int TYPE_GC = 1;
|
||||
public static final int TYPE_WII = 2;
|
||||
public static final int TYPE_OTHER = 3;
|
||||
|
||||
private int mType;
|
||||
private String mFilename;
|
||||
private String mPath;
|
||||
|
||||
public FileListItem(File file)
|
||||
{
|
||||
mPath = file.getAbsolutePath();
|
||||
|
||||
if (file.isDirectory())
|
||||
{
|
||||
mType = TYPE_FOLDER;
|
||||
}
|
||||
else
|
||||
{
|
||||
String fileExtension = mPath.substring(mPath.lastIndexOf('.'));
|
||||
|
||||
// Extensions to filter by.
|
||||
Set<String> allowedExtensions = new HashSet<String>(Arrays.asList(".dff", ".dol", ".elf", ".gcm", ".gcz", ".iso", ".wad", ".wbfs"));
|
||||
|
||||
// Check that the file has an appropriate extension before trying to read out of it.
|
||||
if (allowedExtensions.contains(fileExtension))
|
||||
{
|
||||
mType = NativeLibrary.IsWiiTitle(mPath) ? TYPE_WII : TYPE_GC;
|
||||
}
|
||||
else
|
||||
{
|
||||
mType = TYPE_OTHER;
|
||||
}
|
||||
}
|
||||
|
||||
mFilename = file.getName();
|
||||
}
|
||||
|
||||
public int getType()
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
public String getFilename()
|
||||
{
|
||||
return mFilename;
|
||||
}
|
||||
|
||||
public String getPath()
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(FileListItem theOther)
|
||||
{
|
||||
if (theOther.getType() == getType())
|
||||
{
|
||||
return getFilename().toLowerCase().compareTo(theOther.getFilename().toLowerCase());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (getType() > theOther.getType())
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package org.dolphinemu.dolphinemu.viewholders;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
|
||||
|
||||
public class FileViewHolder extends RecyclerView.ViewHolder
|
||||
{
|
||||
public View itemView;
|
||||
|
||||
public TextView textFileName;
|
||||
public ImageView imageType;
|
||||
|
||||
public FileViewHolder(View itemView)
|
||||
{
|
||||
super(itemView);
|
||||
|
||||
this.itemView = itemView;
|
||||
|
||||
textFileName = (TextView) itemView.findViewById(R.id.text_file_name);
|
||||
imageType = (ImageView) itemView.findViewById(R.id.image_type);
|
||||
}
|
||||
}
|
@ -19,7 +19,6 @@ public class GameViewHolder extends RecyclerView.ViewHolder
|
||||
public ImageView imageScreenshot;
|
||||
public TextView textGameTitle;
|
||||
public TextView textDescription;
|
||||
public ImageButton buttonDetails;
|
||||
|
||||
// Used to handle onClick(). Set this in onBindViewHolder().
|
||||
public String path;
|
||||
@ -30,54 +29,10 @@ public class GameViewHolder extends RecyclerView.ViewHolder
|
||||
{
|
||||
super(itemView);
|
||||
|
||||
itemView.setOnClickListener(mCardClickListener);
|
||||
itemView.setTag(this);
|
||||
|
||||
imageScreenshot = (ImageView) itemView.findViewById(R.id.image_game_screen);
|
||||
textGameTitle = (TextView) itemView.findViewById(R.id.text_game_title);
|
||||
textDescription = (TextView) itemView.findViewById(R.id.text_game_description);
|
||||
buttonDetails = (ImageButton) itemView.findViewById(R.id.button_details);
|
||||
|
||||
buttonDetails.setOnClickListener(mDetailsButtonListener);
|
||||
}
|
||||
|
||||
private View.OnClickListener mCardClickListener = new View.OnClickListener()
|
||||
{
|
||||
/**
|
||||
* Launches the game that was clicked on.
|
||||
*
|
||||
* @param view The card representing the game the user wants to play.
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
// Start the emulation activity and send the path of the clicked ROM to it.
|
||||
Intent intent = new Intent(view.getContext(), EmulationActivity.class);
|
||||
|
||||
intent.putExtra("SelectedGame", path);
|
||||
|
||||
view.getContext().startActivity(intent);
|
||||
}
|
||||
};
|
||||
|
||||
private View.OnClickListener mDetailsButtonListener = new View.OnClickListener()
|
||||
{
|
||||
|
||||
/**
|
||||
* Launches the details activity for this Game, using an ID stored in the
|
||||
* details button's Tag.
|
||||
*
|
||||
* @param view The Details button that was clicked on.
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View view)
|
||||
{
|
||||
// Get the ID of the game we want to look at.
|
||||
// TODO This should be all we need to pass in, eventually.
|
||||
// String gameId = (String) view.getTag();
|
||||
|
||||
Activity activity = (Activity) view.getContext();
|
||||
GameDetailsDialog.newInstance(game).show(activity.getFragmentManager(), "game_details");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
BIN
Source/Android/app/src/main/res/drawable-hdpi/ic_add.png
Normal file
After Width: | Height: | Size: 223 B |
BIN
Source/Android/app/src/main/res/drawable-hdpi/ic_folder.png
Normal file
After Width: | Height: | Size: 224 B |
BIN
Source/Android/app/src/main/res/drawable-hdpi/ic_gamecube.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
Source/Android/app/src/main/res/drawable-hdpi/ic_wii.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
Source/Android/app/src/main/res/drawable-mdpi/ic_add.png
Normal file
After Width: | Height: | Size: 174 B |
BIN
Source/Android/app/src/main/res/drawable-mdpi/ic_folder.png
Normal file
After Width: | Height: | Size: 206 B |
BIN
Source/Android/app/src/main/res/drawable-mdpi/ic_gamecube.png
Normal file
After Width: | Height: | Size: 825 B |
BIN
Source/Android/app/src/main/res/drawable-mdpi/ic_wii.png
Normal file
After Width: | Height: | Size: 608 B |
BIN
Source/Android/app/src/main/res/drawable-xhdpi/ic_add.png
Normal file
After Width: | Height: | Size: 198 B |
BIN
Source/Android/app/src/main/res/drawable-xhdpi/ic_folder.png
Normal file
After Width: | Height: | Size: 273 B |
BIN
Source/Android/app/src/main/res/drawable-xhdpi/ic_gamecube.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
Source/Android/app/src/main/res/drawable-xhdpi/ic_wii.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
Source/Android/app/src/main/res/drawable-xxhdpi/ic_add.png
Normal file
After Width: | Height: | Size: 222 B |
BIN
Source/Android/app/src/main/res/drawable-xxhdpi/ic_folder.png
Normal file
After Width: | Height: | Size: 342 B |
BIN
Source/Android/app/src/main/res/drawable-xxhdpi/ic_gamecube.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
Source/Android/app/src/main/res/drawable-xxhdpi/ic_wii.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
Source/Android/app/src/main/res/drawable-xxxhdpi/ic_add.png
Normal file
After Width: | Height: | Size: 269 B |
BIN
Source/Android/app/src/main/res/drawable-xxxhdpi/ic_folder.png
Normal file
After Width: | Height: | Size: 504 B |
BIN
Source/Android/app/src/main/res/drawable-xxxhdpi/ic_gamecube.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
Source/Android/app/src/main/res/drawable-xxxhdpi/ic_wii.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
@ -1,9 +1,8 @@
|
||||
<!-- res/drawable/oval_ripple.xml -->
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="?android:colorControlHighlight">
|
||||
<item>
|
||||
<shape android:shape="oval">
|
||||
<solid android:color="@color/dolphin_wii"/>
|
||||
<solid android:color="@color/dolphin_accent_gamecube"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
@ -0,0 +1,8 @@
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="?android:colorControlHighlight">
|
||||
<item>
|
||||
<shape android:shape="oval">
|
||||
<solid android:color="@color/circle_grey"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
@ -0,0 +1,8 @@
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="?android:colorControlHighlight">
|
||||
<item>
|
||||
<shape android:shape="oval">
|
||||
<solid android:color="@color/dolphin_accent_wii"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<Toolbar
|
||||
android:id="@+id/toolbar_folder_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/dolphin_blue"
|
||||
android:minHeight="?android:attr/actionBarSize"
|
||||
android:theme="@android:style/ThemeOverlay.Material.Dark.ActionBar"
|
||||
android:elevation="6dp"/>
|
||||
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/list_files"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"
|
||||
tools:listitem="@layout/list_item_file"
|
||||
android:elevation="4dp"
|
||||
android:background="@android:color/white"/>
|
||||
|
||||
|
||||
</LinearLayout>
|
@ -9,16 +9,36 @@
|
||||
android:id="@+id/toolbar_game_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/dolphin_wii"
|
||||
android:background="@color/dolphin_blue"
|
||||
android:minHeight="?android:attr/actionBarSize"
|
||||
android:theme="@android:style/ThemeOverlay.Material.Dark.ActionBar"/>
|
||||
android:theme="@android:style/ThemeOverlay.Material.Dark.ActionBar"
|
||||
android:elevation="6dp"/>
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/grid_games"
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:listitem="@layout/grid_card_game"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"/>
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/grid_games"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:listitem="@layout/grid_card_game"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/button_add_directory"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_alignBottom="@+id/image_game_screen"
|
||||
android:layout_alignEnd="@+id/text_game_title"
|
||||
android:layout_marginBottom="28dp"
|
||||
android:background="@drawable/oval_ripple_gc"
|
||||
android:src="@drawable/ic_add"
|
||||
android:stateListAnimator="@anim/button_elevation"
|
||||
android:elevation="4dp"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"/>
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
@ -2,9 +2,14 @@
|
||||
|
||||
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="250dp"
|
||||
android:transitionName="card_game">
|
||||
android:layout_width="0dp"
|
||||
tools:layout_width="224dp"
|
||||
android:layout_height="256dp"
|
||||
android:transitionName="card_game"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@ -15,56 +20,39 @@
|
||||
android:id="@+id/image_game_screen"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:transitionName="image_game_screen"
|
||||
android:layout_weight="1"
|
||||
tools:src="@drawable/placeholder_screenshot"/>
|
||||
tools:src="@drawable/placeholder_screenshot"
|
||||
tools:scaleType="centerCrop"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="72dp">
|
||||
<TextView
|
||||
android:id="@+id/text_game_title"
|
||||
style="@android:style/TextAppearance.Material.Subhead"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_toStartOf="@+id/button_details"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
tools:text="The Legend of Zelda: The Wind Waker"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_game_description"
|
||||
style="@android:style/TextAppearance.Material.Caption"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
tools:text="Zany rhythm action!"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_game_title"
|
||||
style="@android:style/TextAppearance.Material.Subhead"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@+id/image_game_screen"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_toStartOf="@+id/button_details"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
tools:text="Rhythm Heaven Fever"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_game_description"
|
||||
style="@android:style/TextAppearance.Material.Caption"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignEnd="@+id/text_game_title"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignStart="@+id/text_game_title"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_toStartOf="@+id/button_details"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus sed odio vel quam auctor euismod. Pellentesque odio nibh, fermentum ut hendrerit id, ultrices et justo. "
|
||||
tools:text="Zany rhythm action!"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/button_details"
|
||||
style="@android:style/Widget.Material.Light.Button.Borderless.Small"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignTop="@+id/text_game_title"
|
||||
android:src="@drawable/ic_action_overflow"/>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v7.widget.CardView>
|
||||
|
@ -31,7 +31,6 @@
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:scaleType="centerCrop"
|
||||
android:transitionName="image_game_screen"
|
||||
tools:src="@drawable/placeholder_screenshot"/>
|
||||
|
||||
@ -125,7 +124,7 @@
|
||||
android:layout_alignBottom="@+id/image_game_screen"
|
||||
android:layout_alignEnd="@+id/text_game_title"
|
||||
android:layout_marginBottom="-28dp"
|
||||
android:background="@drawable/oval_ripple"
|
||||
android:background="@drawable/oval_ripple_wii"
|
||||
android:src="@drawable/ic_play"
|
||||
android:stateListAnimator="@anim/button_elevation"
|
||||
android:elevation="4dp"/>
|
||||
|
31
Source/Android/app/src/main/res/layout/list_item_file.xml
Normal file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_type"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:background="@drawable/oval_ripple_grey"
|
||||
android:padding="4dp"
|
||||
tools:src="@drawable/ic_wii"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_file_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_weight="1"
|
||||
android:textSize="16sp"
|
||||
tools:text="File Name"/>
|
||||
|
||||
</LinearLayout>
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- TODO Please give me an icon! -->
|
||||
<item
|
||||
android:id="@+id/menu_up_one_level"
|
||||
android:title="@string/add_directory_up_one_level"
|
||||
android:showAsAction="ifRoom|withText"/>
|
||||
</menu>
|
7
Source/Android/app/src/main/res/menu/menu_game_grid.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/clearGameList"
|
||||
android:title="@string/clear_game_list"
|
||||
android:showAsAction="never"/>
|
||||
</menu>
|
@ -1,8 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="dolphin_wii">#5bc0de</color>
|
||||
<color name="dolphin_wii_dark">#428bca</color>
|
||||
<color name="dolphin_blue">#2196f3</color>
|
||||
<color name="dolphin_blue_dark">#1976d2</color>
|
||||
|
||||
<color name="dolphin_gamecube">#663399</color>
|
||||
<color name="dolphin_gamecube_dark">#311b92</color>
|
||||
<color name="dolphin_accent_wii">#9e9e9e</color>
|
||||
<color name="dolphin_accent_wiiware">#2979ff</color>
|
||||
<color name="dolphin_accent_gamecube">#651fff</color>
|
||||
|
||||
<color name="circle_grey">#bdbdbd</color>
|
||||
</resources>
|
@ -220,4 +220,8 @@
|
||||
<string name="disabled">Disabled</string>
|
||||
<string name="other">Other</string>
|
||||
|
||||
|
||||
<string name="add_directory_title">Add Folder to Library</string>
|
||||
<string name="add_directory_up_one_level">Up one level</string>
|
||||
<string name="add_directory_empty_folder">That folder is empty.</string>
|
||||
</resources>
|
||||
|
@ -1,27 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- inherit from the material theme -->
|
||||
<style name="DolphinWii" parent="android:Theme.Material.Light.NoActionBar">
|
||||
<style name="DolphinBase" parent="android:Theme.Material.Light.NoActionBar">
|
||||
<!-- Main theme colors -->
|
||||
<!-- your app branding color for the app bar -->
|
||||
<item name="android:colorPrimary">@color/dolphin_wii</item>
|
||||
<item name="android:colorPrimary">@color/dolphin_blue</item>
|
||||
<!-- darker variant for the status bar and contextual app bars -->
|
||||
<item name="android:colorPrimaryDark">@color/dolphin_wii_dark</item>
|
||||
<item name="android:colorPrimaryDark">@color/dolphin_blue_dark</item>
|
||||
</style>
|
||||
|
||||
<!-- Inherit from the Base Dolphin Theme-->
|
||||
<style name="DolphinWii" parent="DolphinBase">
|
||||
<!-- theme UI controls like checkboxes and text fields -->
|
||||
<item name="android:colorAccent">@color/dolphin_gamecube</item>
|
||||
<item name="android:colorAccent">@color/dolphin_accent_wii</item>
|
||||
</style>
|
||||
|
||||
<style name="DolphinGamecube" parent="android:Theme.Material.Light.NoActionBar">
|
||||
<item name="android:colorPrimary">@color/dolphin_gamecube</item>
|
||||
<item name="android:colorPrimaryDark">@color/dolphin_gamecube_dark</item>
|
||||
<item name="android:colorAccent">@color/dolphin_wii</item>
|
||||
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowActionBar">false</item>
|
||||
<style name="DolphinGamecube" parent="DolphinBase">
|
||||
<!-- theme UI controls like checkboxes and text fields -->
|
||||
<item name="android:colorAccent">@color/dolphin_accent_gamecube</item>
|
||||
</style>
|
||||
|
||||
<style name="DolphinWiiTransparent" parent="android:Theme.Material.Light.NoActionBar.TranslucentDecor">
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<style name="DolphinWiiware" parent="DolphinBase">
|
||||
<!-- theme UI controls like checkboxes and text fields -->
|
||||
<item name="android:colorAccent">@color/dolphin_accent_wiiware</item>
|
||||
</style>
|
||||
</resources>
|
BIN
Source/Android/code-style-java.jar
Normal file
@ -219,7 +219,7 @@ static std::string GetTitle(std::string filename)
|
||||
return name;
|
||||
}
|
||||
|
||||
return std::string ("Error");
|
||||
return std::string ("");
|
||||
}
|
||||
|
||||
static std::string GetDescription(std::string filename)
|
||||
@ -256,7 +256,7 @@ static std::string GetDescription(std::string filename)
|
||||
return descriptions.cbegin()->second;
|
||||
}
|
||||
|
||||
return std::string ("Error");
|
||||
return std::string ("");
|
||||
}
|
||||
|
||||
static std::string GetGameId(std::string filename)
|
||||
@ -271,7 +271,7 @@ static std::string GetGameId(std::string filename)
|
||||
|
||||
return id;
|
||||
}
|
||||
return std::string ("Error");
|
||||
return std::string ("");
|
||||
}
|
||||
|
||||
static std::string GetApploaderDate(std::string filename)
|
||||
@ -286,7 +286,7 @@ static std::string GetApploaderDate(std::string filename)
|
||||
|
||||
return date;
|
||||
}
|
||||
return std::string ("Error");
|
||||
return std::string ("");
|
||||
}
|
||||
|
||||
static u64 GetFileSize(std::string filename)
|
||||
@ -349,17 +349,17 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_UnPauseEmulation(JNIEnv *env, jobject obj)
|
||||
{
|
||||
PowerPC::Start();
|
||||
PowerPC::Start();
|
||||
}
|
||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_PauseEmulation(JNIEnv *env, jobject obj)
|
||||
{
|
||||
PowerPC::Pause();
|
||||
PowerPC::Pause();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_StopEmulation(JNIEnv *env, jobject obj)
|
||||
{
|
||||
Core::Stop();
|
||||
updateMainFrameEvent.Set(); // Kick the waiting event
|
||||
Core::Stop();
|
||||
updateMainFrameEvent.Set(); // Kick the waiting event
|
||||
}
|
||||
JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_onGamePadEvent(JNIEnv *env, jobject obj, jstring jDevice, jint Button, jint Action)
|
||||
{
|
||||
@ -367,7 +367,7 @@ JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_onGamePa
|
||||
}
|
||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_onGamePadMoveEvent(JNIEnv *env, jobject obj, jstring jDevice, jint Axis, jfloat Value)
|
||||
{
|
||||
ButtonManager::GamepadAxisEvent(GetJString(env, jDevice), Axis, Value);
|
||||
ButtonManager::GamepadAxisEvent(GetJString(env, jDevice), Axis, Value);
|
||||
}
|
||||
|
||||
JNIEXPORT jintArray JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetBanner(JNIEnv *env, jobject obj, jstring jFile)
|
||||
@ -437,12 +437,12 @@ JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Supports
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveScreenShot(JNIEnv *env, jobject obj)
|
||||
{
|
||||
Core::SaveScreenShot();
|
||||
Core::SaveScreenShot();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_eglBindAPI(JNIEnv *env, jobject obj, jint api)
|
||||
{
|
||||
eglBindAPI(api);
|
||||
eglBindAPI(api);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetConfig(JNIEnv *env, jobject obj, jstring jFile, jstring jSection, jstring jKey, jstring jDefault)
|
||||
@ -460,59 +460,58 @@ JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetConfig
|
||||
|
||||
return env->NewStringUTF(value.c_str());
|
||||
}
|
||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetConfig(JNIEnv *env, jobject obj, jstring jFile, jstring jSection, jstring jKey,
|
||||
jstring jValue)
|
||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetConfig(JNIEnv *env, jobject obj, jstring jFile, jstring jSection, jstring jKey, jstring jValue)
|
||||
{
|
||||
IniFile ini;
|
||||
std::string file = GetJString(env, jFile);
|
||||
std::string section = GetJString(env, jSection);
|
||||
std::string key = GetJString(env, jKey);
|
||||
std::string value = GetJString(env, jValue);
|
||||
IniFile ini;
|
||||
std::string file = GetJString(env, jFile);
|
||||
std::string section = GetJString(env, jSection);
|
||||
std::string key = GetJString(env, jKey);
|
||||
std::string value = GetJString(env, jValue);
|
||||
|
||||
ini.Load(File::GetUserPath(D_CONFIG_IDX) + std::string(file));
|
||||
ini.Load(File::GetUserPath(D_CONFIG_IDX) + std::string(file));
|
||||
|
||||
ini.GetOrCreateSection(section)->Set(key, value);
|
||||
ini.Save(File::GetUserPath(D_CONFIG_IDX) + std::string(file));
|
||||
ini.GetOrCreateSection(section)->Set(key, value);
|
||||
ini.Save(File::GetUserPath(D_CONFIG_IDX) + std::string(file));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetFilename(JNIEnv *env, jobject obj, jstring jFile)
|
||||
{
|
||||
g_filename = GetJString(env, jFile);
|
||||
g_filename = GetJString(env, jFile);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveState(JNIEnv *env, jobject obj, jint slot)
|
||||
{
|
||||
State::Save(slot);
|
||||
State::Save(slot);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadState(JNIEnv *env, jobject obj, jint slot)
|
||||
{
|
||||
State::Load(slot);
|
||||
State::Load(slot);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_CreateUserFolders(JNIEnv *env, jobject obj)
|
||||
{
|
||||
File::CreateFullPath(File::GetUserPath(D_CONFIG_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_WIIUSER_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_CACHE_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_DUMPDSP_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_DUMPTEXTURES_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_HIRESTEXTURES_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_SCREENSHOTS_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_STATESAVES_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_MAILLOGS_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_SHADERS_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + USA_DIR DIR_SEP);
|
||||
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + EUR_DIR DIR_SEP);
|
||||
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + JAP_DIR DIR_SEP);
|
||||
File::CreateFullPath(File::GetUserPath(D_CONFIG_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_WIIUSER_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_CACHE_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_DUMPDSP_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_DUMPTEXTURES_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_HIRESTEXTURES_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_SCREENSHOTS_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_STATESAVES_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_MAILLOGS_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_SHADERS_IDX));
|
||||
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + USA_DIR DIR_SEP);
|
||||
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + EUR_DIR DIR_SEP);
|
||||
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + JAP_DIR DIR_SEP);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetUserDirectory(JNIEnv *env, jobject obj, jstring jDirectory)
|
||||
{
|
||||
std::string directory = GetJString(env, jDirectory);
|
||||
g_set_userpath = directory;
|
||||
UICommon::SetUserDirectory(directory);
|
||||
std::string directory = GetJString(env, jDirectory);
|
||||
g_set_userpath = directory;
|
||||
UICommon::SetUserDirectory(directory);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetUserDirectory(JNIEnv *env, jobject obj)
|
||||
@ -522,24 +521,24 @@ JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetUserDi
|
||||
|
||||
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run(JNIEnv *env, jobject obj, jobject _surf)
|
||||
{
|
||||
surf = ANativeWindow_fromSurface(env, _surf);
|
||||
surf = ANativeWindow_fromSurface(env, _surf);
|
||||
|
||||
// Install our callbacks
|
||||
OSD::AddCallback(OSD::OSD_INIT, ButtonManager::Init);
|
||||
OSD::AddCallback(OSD::OSD_SHUTDOWN, ButtonManager::Shutdown);
|
||||
// Install our callbacks
|
||||
OSD::AddCallback(OSD::OSD_INIT, ButtonManager::Init);
|
||||
OSD::AddCallback(OSD::OSD_SHUTDOWN, ButtonManager::Shutdown);
|
||||
|
||||
RegisterMsgAlertHandler(&MsgAlert);
|
||||
RegisterMsgAlertHandler(&MsgAlert);
|
||||
|
||||
UICommon::SetUserDirectory(g_set_userpath);
|
||||
UICommon::Init();
|
||||
UICommon::SetUserDirectory(g_set_userpath);
|
||||
UICommon::Init();
|
||||
|
||||
// No use running the loop when booting fails
|
||||
if ( BootManager::BootCore( g_filename.c_str() ) )
|
||||
while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
|
||||
updateMainFrameEvent.Wait();
|
||||
// No use running the loop when booting fails
|
||||
if ( BootManager::BootCore( g_filename.c_str() ) )
|
||||
while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
|
||||
updateMainFrameEvent.Wait();
|
||||
|
||||
UICommon::Shutdown();
|
||||
ANativeWindow_release(surf);
|
||||
UICommon::Shutdown();
|
||||
ANativeWindow_release(surf);
|
||||
}
|
||||
|
||||
|
||||
|