Merge pull request #2389 from sigmabeta/lollipop-ui-tweaks
Android: Add file browser screen to new UI, and several tweaks.
@ -3,7 +3,6 @@
|
||||
If you make any contributions to Dolphin after December 1st, 2014, you are agreeing that any code you have contributed will be licensed under the GNU GPL version 2 (or any later version).
|
||||
|
||||
## Coding Style
|
||||
---
|
||||
|
||||
- [Introduction] (#introduction)
|
||||
- [Styling and formatting] (#styling-and-formatting)
|
||||
@ -20,14 +19,12 @@ If you make any contributions to Dolphin after December 1st, 2014, you are agree
|
||||
|
||||
|
||||
## Introduction
|
||||
---
|
||||
|
||||
This guide is for developers who wish to contribute to the Dolphin codebase. It will detail how to properly style and format code to fit this project. This guide also offers suggestions on specific functions and other varia that may be used in code.
|
||||
|
||||
Following this guide and formatting your code as detailed will likely get your pull request merged much faster than if you don't (assuming the written code has no mistakes in itself).
|
||||
|
||||
## Styling and formatting
|
||||
---
|
||||
|
||||
### General
|
||||
- Try to limit lines of code to a maximum of 100 characters.
|
||||
@ -130,7 +127,6 @@ private:
|
||||
```
|
||||
|
||||
## Code Specific
|
||||
---
|
||||
|
||||
### General
|
||||
- Using C++11 features is OK and recommended.
|
||||
@ -229,3 +225,7 @@ private:
|
||||
// Class definitions
|
||||
};
|
||||
```
|
||||
|
||||
## Java
|
||||
|
||||
The Android project is currently written in Java. If you are using Android Studio to contribute, you can import the project's code style from `code-style-java.jar`, located in `[Dolphin Root]/Source/Android`. Please organize imports before committing.
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|