Reformat Android code

This commit is contained in:
riking
2018-08-26 21:37:54 -07:00
parent ab76631a7f
commit 248ee12aed
102 changed files with 11134 additions and 10354 deletions
+2 -1
View File
@@ -67,7 +67,8 @@ android {
defaultConfig {
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_static", "-DCMAKE_BUILD_TYPE=RelWithDebInfo" // , "-DENABLE_GENERIC=ON"
arguments "-DANDROID_STL=c++_static", "-DCMAKE_BUILD_TYPE=RelWithDebInfo"
// , "-DENABLE_GENERIC=ON"
abiFilters "arm64-v8a", "x86_64" //, "armeabi-v7a", "x86"
}
}
+18 -16
View File
@@ -11,13 +11,13 @@
android:name="android.software.leanback"
android:required="false"/>
<uses-feature android:glEsVersion="0x00030000" />
<uses-feature android:glEsVersion="0x00030000"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" />
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA"/>
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA"/>
<application
android:name=".DolphinApplication"
@@ -27,7 +27,9 @@
android:supportsRtl="true"
android:isGame="true"
android:banner="@drawable/banner_tv">
<meta-data android:name="android.max_aspect" android:value="2.1" />
<meta-data
android:name="android.max_aspect"
android:value="2.1"/>
<activity
android:name=".ui.main.MainActivity"
@@ -67,18 +69,18 @@
android:label="@string/app_name"
android:theme="@style/FilePickerTheme">
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.GET_CONTENT"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity android:name=".activities.AppLinkActivity" >
<activity android:name=".activities.AppLinkActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data
android:host="@string/host"
android:scheme="@string/scheme" />
android:scheme="@string/scheme"/>
</intent-filter>
</activity>
@@ -87,11 +89,11 @@
<service
android:name=".services.SyncChannelJobService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE" />
android:permission="android.permission.BIND_JOB_SERVICE"/>
<service
android:name=".services.SyncProgramsJobService"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE" />
android:permission="android.permission.BIND_JOB_SERVICE"/>
<provider
android:name="android.support.v4.content.FileProvider"
@@ -100,7 +102,7 @@
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/nnf_provider_paths" />
android:resource="@xml/nnf_provider_paths"/>
</provider>
</application>
@@ -8,15 +8,15 @@ import org.dolphinemu.dolphinemu.utils.VolleyUtil;
public class DolphinApplication extends Application
{
@Override
public void onCreate()
{
super.onCreate();
@Override
public void onCreate()
{
super.onCreate();
VolleyUtil.init(getApplicationContext());
System.loadLibrary("main");
VolleyUtil.init(getApplicationContext());
System.loadLibrary("main");
if (PermissionsHandler.hasWriteAccess(getApplicationContext()))
DirectoryInitializationService.startService(getApplicationContext());
}
if (PermissionsHandler.hasWriteAccess(getApplicationContext()))
DirectoryInitializationService.startService(getApplicationContext());
}
}
File diff suppressed because it is too large Load Diff
@@ -22,113 +22,116 @@ import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
*/
public class AppLinkActivity extends FragmentActivity
{
private static final String TAG = "AppLinkActivity";
private static final String TAG = "AppLinkActivity";
private AppLinkHelper.PlayAction playAction;
private DirectoryStateReceiver directoryStateReceiver;
private AppLinkHelper.PlayAction playAction;
private DirectoryStateReceiver directoryStateReceiver;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Intent intent = getIntent();
Uri uri = intent.getData();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Intent intent = getIntent();
Uri uri = intent.getData();
Log.v(TAG, uri.toString());
Log.v(TAG, uri.toString());
if (uri.getPathSegments().isEmpty())
{
Log.e(TAG, "Invalid uri " + uri);
finish();
return;
}
if (uri.getPathSegments().isEmpty())
{
Log.e(TAG, "Invalid uri " + uri);
finish();
return;
}
AppLinkHelper.AppLinkAction action = AppLinkHelper.extractAction(uri);
switch (action.getAction())
{
case AppLinkHelper.PLAY:
playAction = (AppLinkHelper.PlayAction) action;
initResources();
break;
case AppLinkHelper.BROWSE:
browse();
break;
default:
throw new IllegalArgumentException("Invalid Action " + action);
}
}
AppLinkHelper.AppLinkAction action = AppLinkHelper.extractAction(uri);
switch (action.getAction())
{
case AppLinkHelper.PLAY:
playAction = (AppLinkHelper.PlayAction) action;
initResources();
break;
case AppLinkHelper.BROWSE:
browse();
break;
default:
throw new IllegalArgumentException("Invalid Action " + action);
}
}
/**
* Need to init these since they usually occur in the main activity.
*/
private void initResources()
{
IntentFilter statusIntentFilter = new IntentFilter(
DirectoryInitializationService.BROADCAST_ACTION);
/**
* Need to init these since they usually occur in the main activity.
*/
private void initResources()
{
IntentFilter statusIntentFilter = new IntentFilter(
DirectoryInitializationService.BROADCAST_ACTION);
directoryStateReceiver =
new DirectoryStateReceiver(directoryInitializationState ->
{
if (directoryInitializationState == DirectoryInitializationService.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
{
play(playAction);
}
else if (directoryInitializationState == DirectoryInitializationService.DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED)
{
Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
.show();
}
else if (directoryInitializationState == DirectoryInitializationService.DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE)
{
Toast.makeText(this, R.string.external_storage_not_mounted, Toast.LENGTH_SHORT)
.show();
}
});
directoryStateReceiver =
new DirectoryStateReceiver(directoryInitializationState ->
{
if (directoryInitializationState ==
DirectoryInitializationService.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
{
play(playAction);
}
else if (directoryInitializationState ==
DirectoryInitializationService.DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED)
{
Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
.show();
}
else if (directoryInitializationState ==
DirectoryInitializationService.DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE)
{
Toast.makeText(this, R.string.external_storage_not_mounted, Toast.LENGTH_SHORT)
.show();
}
});
// Registers the DirectoryStateReceiver and its intent filters
LocalBroadcastManager.getInstance(this).registerReceiver(
directoryStateReceiver,
statusIntentFilter);
DirectoryInitializationService.startService(this);
GameFileCacheService.startLoad(this);
}
// Registers the DirectoryStateReceiver and its intent filters
LocalBroadcastManager.getInstance(this).registerReceiver(
directoryStateReceiver,
statusIntentFilter);
DirectoryInitializationService.startService(this);
GameFileCacheService.startLoad(this);
}
/**
* Action if channel icon is selected
*/
private void browse()
{
Intent openApp = new Intent(this, TvMainActivity.class);
startActivity(openApp);
/**
* Action if channel icon is selected
*/
private void browse()
{
Intent openApp = new Intent(this, TvMainActivity.class);
startActivity(openApp);
finish();
}
finish();
}
/**
* Action if program(game) is selected
*/
private void play(AppLinkHelper.PlayAction action)
{
Log.d(TAG, "Playing game "
+ action.getGameId()
+ " from channel "
+ action.getChannelId());
/**
* Action if program(game) is selected
*/
private void play(AppLinkHelper.PlayAction action)
{
Log.d(TAG, "Playing game "
+ action.getGameId()
+ " from channel "
+ action.getChannelId());
GameFile game = GameFileCacheService.getGameFileByGameId(action.getGameId());
if (game == null)
Log.e(TAG, "Invalid Game: " + action.getGameId());
else
startGame(game);
finish();
}
GameFile game = GameFileCacheService.getGameFileByGameId(action.getGameId());
if (game == null)
Log.e(TAG, "Invalid Game: " + action.getGameId());
else
startGame(game);
finish();
}
private void startGame(GameFile game)
{
if (directoryStateReceiver != null)
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(directoryStateReceiver);
directoryStateReceiver = null;
}
EmulationActivity.launch(this, game, -1, null);
}
private void startGame(GameFile game)
{
if (directoryStateReceiver != null)
{
LocalBroadcastManager.getInstance(this).unregisterReceiver(directoryStateReceiver);
directoryStateReceiver = null;
}
EmulationActivity.launch(this, game, -1, null);
}
}
@@ -13,16 +13,17 @@ import java.io.File;
public class CustomFilePickerActivity extends FilePickerActivity
{
@Override
protected AbstractFilePickerFragment<File> getFragment(
@Nullable final String startPath, final int mode, final boolean allowMultiple,
final boolean allowCreateDir, final boolean allowExistingFile,
final boolean singleClick)
{
AbstractFilePickerFragment<File> fragment = new CustomFilePickerFragment();
// startPath is allowed to be null. In that case, default folder should be SD-card and not "/"
fragment.setArgs(startPath != null ? startPath : Environment.getExternalStorageDirectory().getPath(),
mode, allowMultiple, allowCreateDir, allowExistingFile, singleClick);
return fragment;
}
@Override
protected AbstractFilePickerFragment<File> getFragment(
@Nullable final String startPath, final int mode, final boolean allowMultiple,
final boolean allowCreateDir, final boolean allowExistingFile,
final boolean singleClick)
{
AbstractFilePickerFragment<File> fragment = new CustomFilePickerFragment();
// startPath is allowed to be null. In that case, default folder should be SD-card and not "/"
fragment.setArgs(
startPath != null ? startPath : Environment.getExternalStorageDirectory().getPath(),
mode, allowMultiple, allowCreateDir, allowExistingFile, singleClick);
return fragment;
}
}
@@ -12,10 +12,10 @@ import android.widget.Toast;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
import org.dolphinemu.dolphinemu.model.GameFile;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity;
import org.dolphinemu.dolphinemu.model.GameFile;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
import org.dolphinemu.dolphinemu.utils.PicassoUtils;
import org.dolphinemu.dolphinemu.viewholders.GameViewHolder;
@@ -24,186 +24,195 @@ import java.util.ArrayList;
import java.util.List;
public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> implements
View.OnClickListener,
View.OnLongClickListener
View.OnClickListener,
View.OnLongClickListener
{
private List<GameFile> mGameFiles;
private List<GameFile> mGameFiles;
/**
* Initializes the adapter's observer, which watches for changes to the dataset. The adapter will
* display no data until swapDataSet is called.
*/
public GameAdapter()
{
mGameFiles = new ArrayList<>();
}
/**
* Initializes the adapter's observer, which watches for changes to the dataset. The adapter will
* display no data until swapDataSet is called.
*/
public GameAdapter()
{
mGameFiles = new ArrayList<>();
}
/**
* 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 GameViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
// Create a new view.
View gameCard = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_game, parent, false);
/**
* 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 GameViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
// Create a new view.
View gameCard = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_game, parent, false);
gameCard.setOnClickListener(this);
gameCard.setOnLongClickListener(this);
gameCard.setOnClickListener(this);
gameCard.setOnLongClickListener(this);
// Use that view to create a ViewHolder.
return new GameViewHolder(gameCard);
}
// Use that view to create a ViewHolder.
return new GameViewHolder(gameCard);
}
/**
* 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(GameViewHolder holder, int position)
{
GameFile gameFile = mGameFiles.get(position);
PicassoUtils.loadGameBanner(holder.imageScreenshot, gameFile);
/**
* 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(GameViewHolder holder, int position)
{
GameFile gameFile = mGameFiles.get(position);
PicassoUtils.loadGameBanner(holder.imageScreenshot, gameFile);
holder.textGameTitle.setText(gameFile.getTitle());
holder.textCompany.setText(gameFile.getCompany());
holder.textGameTitle.setText(gameFile.getTitle());
holder.textCompany.setText(gameFile.getCompany());
holder.gameFile = gameFile;
}
holder.gameFile = gameFile;
}
/**
* Called by the LayoutManager to find out how much data we have.
*
* @return Size of the dataset.
*/
@Override
public int getItemCount()
{
return mGameFiles.size();
}
/**
* Called by the LayoutManager to find out how much data we have.
*
* @return Size of the dataset.
*/
@Override
public int getItemCount()
{
return mGameFiles.size();
}
/**
* Tell Android whether or not each item in the dataset has a stable identifier.
*
* @param hasStableIds ignored.
*/
@Override
public void setHasStableIds(boolean hasStableIds)
{
super.setHasStableIds(false);
}
/**
* Tell Android whether or not each item in the dataset has a stable identifier.
*
* @param hasStableIds ignored.
*/
@Override
public void setHasStableIds(boolean hasStableIds)
{
super.setHasStableIds(false);
}
/**
* When a load is finished, call this to replace the existing data
* with the newly-loaded data.
*/
public void swapDataSet(List<GameFile> gameFiles)
{
mGameFiles = gameFiles;
notifyDataSetChanged();
}
/**
* When a load is finished, call this to replace the existing data
* with the newly-loaded data.
*/
public void swapDataSet(List<GameFile> gameFiles)
{
mGameFiles = gameFiles;
notifyDataSetChanged();
}
/**
* 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();
/**
* 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();
EmulationActivity.launch((FragmentActivity) view.getContext(),
holder.gameFile,
holder.getAdapterPosition(),
holder.imageScreenshot);
}
EmulationActivity.launch((FragmentActivity) view.getContext(),
holder.gameFile,
holder.getAdapterPosition(),
holder.imageScreenshot);
}
/**
* 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)
{
FragmentActivity activity = (FragmentActivity) view.getContext();
GameViewHolder holder = (GameViewHolder) view.getTag();
String gameId = holder.gameFile.getGameId();
/**
* 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)
{
FragmentActivity activity = (FragmentActivity) view.getContext();
GameViewHolder holder = (GameViewHolder) view.getTag();
String gameId = holder.gameFile.getGameId();
if (gameId.isEmpty())
{
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Game Settings");
builder.setMessage("Files without game IDs don't support game-specific settings.");
if (gameId.isEmpty())
{
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Game Settings");
builder.setMessage("Files without game IDs don't support game-specific settings.");
builder.show();
return true;
}
builder.show();
return true;
}
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Game Settings")
.setItems(R.array.gameSettingsMenus, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0:
SettingsActivity.launch(activity, MenuTag.CONFIG, gameId);
break;
case 1:
SettingsActivity.launch(activity, MenuTag.GRAPHICS, gameId);
break;
case 2:
String path = DirectoryInitializationService.getUserDirectory() + "/GameSettings/" + gameId + ".ini";
File gameSettingsFile = new File(path);
if (gameSettingsFile.exists())
{
if (gameSettingsFile.delete())
{
Toast.makeText(view.getContext(), "Cleared settings for " + gameId, Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(view.getContext(), "Unable to clear settings for " + gameId, Toast.LENGTH_SHORT).show();
}
}
else
{
Toast.makeText(view.getContext(), "No game settings to delete", Toast.LENGTH_SHORT).show();
}
break;
}
}
});
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Game Settings")
.setItems(R.array.gameSettingsMenus, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
switch (which)
{
case 0:
SettingsActivity.launch(activity, MenuTag.CONFIG, gameId);
break;
case 1:
SettingsActivity.launch(activity, MenuTag.GRAPHICS, gameId);
break;
case 2:
String path =
DirectoryInitializationService.getUserDirectory() + "/GameSettings/" +
gameId + ".ini";
File gameSettingsFile = new File(path);
if (gameSettingsFile.exists())
{
if (gameSettingsFile.delete())
{
Toast.makeText(view.getContext(), "Cleared settings for " + gameId,
Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(view.getContext(), "Unable to clear settings for " + gameId,
Toast.LENGTH_SHORT).show();
}
}
else
{
Toast.makeText(view.getContext(), "No game settings to delete",
Toast.LENGTH_SHORT).show();
}
break;
}
}
});
builder.show();
return true;
}
builder.show();
return true;
}
public static class SpacesItemDecoration extends RecyclerView.ItemDecoration
{
private int space;
public static class SpacesItemDecoration extends RecyclerView.ItemDecoration
{
private int space;
public SpacesItemDecoration(int space)
{
this.space = space;
}
public SpacesItemDecoration(int space)
{
this.space = space;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state)
{
outRect.left = space;
outRect.right = space;
outRect.bottom = space;
outRect.top = space;
}
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state)
{
outRect.left = space;
outRect.right = space;
outRect.bottom = space;
outRect.top = space;
}
}
}
@@ -14,11 +14,11 @@ import android.widget.ImageView;
import android.widget.Toast;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity;
import org.dolphinemu.dolphinemu.model.GameFile;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
import org.dolphinemu.dolphinemu.ui.platform.Platform;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity;
import org.dolphinemu.dolphinemu.utils.PicassoUtils;
import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder;
@@ -30,117 +30,126 @@ import java.io.File;
*/
public final class GameRowPresenter extends Presenter
{
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent)
{
// Create a new view.
ImageCardView gameCard = new ImageCardView(parent.getContext());
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent)
{
// Create a new view.
ImageCardView gameCard = new ImageCardView(parent.getContext());
gameCard.setMainImageAdjustViewBounds(true);
gameCard.setMainImageDimensions(240, 336);
gameCard.setMainImageScaleType(ImageView.ScaleType.CENTER_CROP);
gameCard.setMainImageAdjustViewBounds(true);
gameCard.setMainImageDimensions(240, 336);
gameCard.setMainImageScaleType(ImageView.ScaleType.CENTER_CROP);
gameCard.setFocusable(true);
gameCard.setFocusableInTouchMode(true);
gameCard.setFocusable(true);
gameCard.setFocusableInTouchMode(true);
// Use that view to create a ViewHolder.
return new TvGameViewHolder(gameCard);
}
// Use that view to create a ViewHolder.
return new TvGameViewHolder(gameCard);
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, Object item)
{
TvGameViewHolder holder = (TvGameViewHolder) viewHolder;
GameFile gameFile = (GameFile) item;
@Override
public void onBindViewHolder(ViewHolder viewHolder, Object item)
{
TvGameViewHolder holder = (TvGameViewHolder) viewHolder;
GameFile gameFile = (GameFile) item;
holder.imageScreenshot.setImageDrawable(null);
PicassoUtils.loadGameBanner(holder.imageScreenshot, gameFile);
holder.imageScreenshot.setImageDrawable(null);
PicassoUtils.loadGameBanner(holder.imageScreenshot, gameFile);
holder.cardParent.setTitleText(gameFile.getTitle());
holder.cardParent.setContentText(gameFile.getCompany());
holder.cardParent.setTitleText(gameFile.getTitle());
holder.cardParent.setContentText(gameFile.getCompany());
holder.gameFile = gameFile;
holder.gameFile = gameFile;
// Set the platform-dependent background color of the card
int backgroundId;
switch (Platform.fromNativeInt(gameFile.getPlatform()))
{
case GAMECUBE:
backgroundId = R.drawable.tv_card_background_gamecube;
break;
case WII:
backgroundId = R.drawable.tv_card_background_wii;
break;
case WIIWARE:
backgroundId = R.drawable.tv_card_background_wiiware;
break;
default:
throw new AssertionError("Not reachable.");
}
Context context = holder.cardParent.getContext();
Drawable background = ContextCompat.getDrawable(context, backgroundId);
holder.cardParent.setInfoAreaBackground(background);
holder.cardParent.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view)
{
FragmentActivity activity = (FragmentActivity) view.getContext();
String gameId = gameFile.getGameId();
// Set the platform-dependent background color of the card
int backgroundId;
switch (Platform.fromNativeInt(gameFile.getPlatform()))
{
case GAMECUBE:
backgroundId = R.drawable.tv_card_background_gamecube;
break;
case WII:
backgroundId = R.drawable.tv_card_background_wii;
break;
case WIIWARE:
backgroundId = R.drawable.tv_card_background_wiiware;
break;
default:
throw new AssertionError("Not reachable.");
}
Context context = holder.cardParent.getContext();
Drawable background = ContextCompat.getDrawable(context, backgroundId);
holder.cardParent.setInfoAreaBackground(background);
holder.cardParent.setOnLongClickListener(new View.OnLongClickListener()
{
@Override
public boolean onLongClick(View view)
{
FragmentActivity activity = (FragmentActivity) view.getContext();
String gameId = gameFile.getGameId();
if (gameId.isEmpty())
{
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Game Settings");
builder.setMessage("Files without game IDs don't support game-specific settings.");
if (gameId.isEmpty())
{
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Game Settings");
builder.setMessage("Files without game IDs don't support game-specific settings.");
builder.show();
return true;
}
builder.show();
return true;
}
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Game Settings")
.setItems(R.array.gameSettingsMenus, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case 0:
SettingsActivity.launch(activity, MenuTag.CONFIG, gameId);
break;
case 1:
SettingsActivity.launch(activity, MenuTag.GRAPHICS, gameId);
break;
case 2:
String path = DirectoryInitializationService.getUserDirectory() + "/GameSettings/" + gameId + ".ini";
File gameSettingsFile = new File(path);
if (gameSettingsFile.exists())
{
if (gameSettingsFile.delete())
{
Toast.makeText(view.getContext(), "Cleared settings for " + gameId, Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(view.getContext(), "Unable to clear settings for " + gameId, Toast.LENGTH_SHORT).show();
}
}
else
{
Toast.makeText(view.getContext(), "No game settings to delete", Toast.LENGTH_SHORT).show();
}
break;
}
}
});
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Game Settings")
.setItems(R.array.gameSettingsMenus, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
switch (which)
{
case 0:
SettingsActivity.launch(activity, MenuTag.CONFIG, gameId);
break;
case 1:
SettingsActivity.launch(activity, MenuTag.GRAPHICS, gameId);
break;
case 2:
String path = DirectoryInitializationService.getUserDirectory() +
"/GameSettings/" + gameId + ".ini";
File gameSettingsFile = new File(path);
if (gameSettingsFile.exists())
{
if (gameSettingsFile.delete())
{
Toast.makeText(view.getContext(), "Cleared settings for " + gameId,
Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(view.getContext(),
"Unable to clear settings for " + gameId, Toast.LENGTH_SHORT)
.show();
}
}
else
{
Toast.makeText(view.getContext(), "No game settings to delete",
Toast.LENGTH_SHORT).show();
}
break;
}
}
});
builder.show();
return true;
}
});
}
builder.show();
return true;
}
});
}
@Override
public void onUnbindViewHolder(ViewHolder viewHolder)
{
// no op
}
@Override
public void onUnbindViewHolder(ViewHolder viewHolder)
{
// no op
}
}
@@ -2,9 +2,9 @@ package org.dolphinemu.dolphinemu.adapters;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ImageSpan;
@@ -15,48 +15,48 @@ import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesFragment;
public class PlatformPagerAdapter extends FragmentPagerAdapter
{
private Context mContext;
private Context mContext;
private final static int[] TAB_ICONS =
{
R.drawable.ic_gamecube,
R.drawable.ic_wii,
R.drawable.ic_folder // WiiWare TODO Have an icon here.
};
private final static int[] TAB_ICONS =
{
R.drawable.ic_gamecube,
R.drawable.ic_wii,
R.drawable.ic_folder // WiiWare TODO Have an icon here.
};
public PlatformPagerAdapter(FragmentManager fm, Context context)
{
super(fm);
mContext = context;
}
public PlatformPagerAdapter(FragmentManager fm, Context context)
{
super(fm);
mContext = context;
}
@Override
public Fragment getItem(int position)
{
return PlatformGamesFragment.newInstance(Platform.fromPosition(position));
}
@Override
public Fragment getItem(int position)
{
return PlatformGamesFragment.newInstance(Platform.fromPosition(position));
}
@Override
public int getCount()
{
return TAB_ICONS.length;
}
@Override
public int getCount()
{
return TAB_ICONS.length;
}
@Override
public CharSequence getPageTitle(int position)
{
// Hax from https://guides.codepath.com/android/Google-Play-Style-Tabs-using-TabLayout#design-support-library
// Apparently a workaround for TabLayout not supporting icons.
// TODO This workaround will eventually not be necessary; switch to more legit methods when that is the case
// TODO Also remove additional hax from styles.xml
Drawable drawable = mContext.getResources().getDrawable(TAB_ICONS[position]);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
@Override
public CharSequence getPageTitle(int position)
{
// Hax from https://guides.codepath.com/android/Google-Play-Style-Tabs-using-TabLayout#design-support-library
// Apparently a workaround for TabLayout not supporting icons.
// TODO This workaround will eventually not be necessary; switch to more legit methods when that is the case
// TODO Also remove additional hax from styles.xml
Drawable drawable = mContext.getResources().getDrawable(TAB_ICONS[position]);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM);
ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM);
SpannableString sb = new SpannableString(" ");
sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
SpannableString sb = new SpannableString(" ");
sb.setSpan(imageSpan, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
return sb;
}
return sb;
}
}
@@ -10,37 +10,37 @@ import org.dolphinemu.dolphinemu.viewholders.TvSettingsViewHolder;
public final class SettingsRowPresenter extends Presenter
{
public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent)
{
// Create a new view.
ImageCardView settingsCard = new ImageCardView(parent.getContext());
public Presenter.ViewHolder onCreateViewHolder(ViewGroup parent)
{
// Create a new view.
ImageCardView settingsCard = new ImageCardView(parent.getContext());
settingsCard.setMainImageAdjustViewBounds(true);
settingsCard.setMainImageDimensions(192, 160);
settingsCard.setMainImageAdjustViewBounds(true);
settingsCard.setMainImageDimensions(192, 160);
settingsCard.setFocusable(true);
settingsCard.setFocusableInTouchMode(true);
settingsCard.setFocusable(true);
settingsCard.setFocusableInTouchMode(true);
// Use that view to create a ViewHolder.
return new TvSettingsViewHolder(settingsCard);
}
// Use that view to create a ViewHolder.
return new TvSettingsViewHolder(settingsCard);
}
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item)
{
TvSettingsViewHolder holder = (TvSettingsViewHolder) viewHolder;
TvSettingsItem settingsItem = (TvSettingsItem) item;
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item)
{
TvSettingsViewHolder holder = (TvSettingsViewHolder) viewHolder;
TvSettingsItem settingsItem = (TvSettingsItem) item;
Resources resources = holder.cardParent.getResources();
Resources resources = holder.cardParent.getResources();
holder.itemId = settingsItem.getItemId();
holder.itemId = settingsItem.getItemId();
holder.cardParent.setTitleText(resources.getString(settingsItem.getLabelId()));
holder.cardParent.setMainImage(resources.getDrawable(settingsItem.getIconId(), null));
}
holder.cardParent.setTitleText(resources.getString(settingsItem.getLabelId()));
holder.cardParent.setMainImage(resources.getDrawable(settingsItem.getIconId(), null));
}
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder)
{
// no op
}
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder)
{
// no op
}
}
@@ -5,14 +5,12 @@ import android.app.Dialog;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.DialogFragment;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import org.dolphinemu.dolphinemu.DolphinApplication;
import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.activities.EmulationActivity;
import org.dolphinemu.dolphinemu.model.GameFile;
@@ -22,63 +20,64 @@ import de.hdodenhof.circleimageview.CircleImageView;
public final class GameDetailsDialog extends DialogFragment
{
private static final String ARG_GAME_PATH = "game_path";
private static final String ARG_GAME_PATH = "game_path";
public static GameDetailsDialog newInstance(String gamePath)
{
GameDetailsDialog fragment = new GameDetailsDialog();
public static GameDetailsDialog newInstance(String gamePath)
{
GameDetailsDialog fragment = new GameDetailsDialog();
Bundle arguments = new Bundle();
arguments.putString(ARG_GAME_PATH, gamePath);
fragment.setArguments(arguments);
Bundle arguments = new Bundle();
arguments.putString(ARG_GAME_PATH, gamePath);
fragment.setArguments(arguments);
return fragment;
}
return fragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
GameFile gameFile = GameFileCacheService.addOrGet(getArguments().getString(ARG_GAME_PATH));
@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
GameFile gameFile = GameFileCacheService.addOrGet(getArguments().getString(ARG_GAME_PATH));
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
ViewGroup contents = (ViewGroup) getActivity().getLayoutInflater().inflate(R.layout.dialog_game_details, null);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
ViewGroup contents = (ViewGroup) getActivity().getLayoutInflater()
.inflate(R.layout.dialog_game_details, null);
final ImageView imageGameScreen = contents.findViewById(R.id.image_game_screen);
CircleImageView circleBanner = contents.findViewById(R.id.circle_banner);
final ImageView imageGameScreen = contents.findViewById(R.id.image_game_screen);
CircleImageView circleBanner = contents.findViewById(R.id.circle_banner);
TextView textTitle = contents.findViewById(R.id.text_game_title);
TextView textDescription = contents.findViewById(R.id.text_description);
TextView textTitle = contents.findViewById(R.id.text_game_title);
TextView textDescription = contents.findViewById(R.id.text_description);
TextView textCountry = contents.findViewById(R.id.text_country);
TextView textCompany = contents.findViewById(R.id.text_company);
TextView textCountry = contents.findViewById(R.id.text_country);
TextView textCompany = contents.findViewById(R.id.text_company);
FloatingActionButton buttonLaunch = contents.findViewById(R.id.button_launch);
FloatingActionButton buttonLaunch = contents.findViewById(R.id.button_launch);
String country = getResources().getStringArray(R.array.countryNames)[gameFile.getCountry()];
String country = getResources().getStringArray(R.array.countryNames)[gameFile.getCountry()];
textTitle.setText(gameFile.getTitle());
textDescription.setText(gameFile.getDescription());
textCountry.setText(country);
textCompany.setText(gameFile.getCompany());
textTitle.setText(gameFile.getTitle());
textDescription.setText(gameFile.getDescription());
textCountry.setText(country);
textCompany.setText(gameFile.getCompany());
buttonLaunch.setOnClickListener(view ->
{
// Start the emulation activity and send the path of the clicked ROM to it.
EmulationActivity.launch(getActivity(), gameFile, -1, imageGameScreen);
});
buttonLaunch.setOnClickListener(view ->
{
// Start the emulation activity and send the path of the clicked ROM to it.
EmulationActivity.launch(getActivity(), gameFile, -1, imageGameScreen);
});
// Fill in the view contents.
Picasso.with(imageGameScreen.getContext())
.load(getArguments().getString(gameFile.getScreenshotPath()))
.fit()
.centerCrop()
.noFade()
.noPlaceholder()
.into(imageGameScreen);
// Fill in the view contents.
Picasso.with(imageGameScreen.getContext())
.load(getArguments().getString(gameFile.getScreenshotPath()))
.fit()
.centerCrop()
.noFade()
.noPlaceholder()
.into(imageGameScreen);
circleBanner.setImageResource(R.drawable.no_banner);
circleBanner.setImageResource(R.drawable.no_banner);
builder.setView(contents);
return builder.create();
}
builder.setView(contents);
return builder.create();
}
}
@@ -22,205 +22,209 @@ import java.util.List;
*/
public final class MotionAlertDialog extends AlertDialog
{
// The selected input preference
private final InputBindingSetting setting;
private final ArrayList<Float> mPreviousValues = new ArrayList<>();
private int mPrevDeviceId = 0;
private boolean mWaitingForEvent = true;
// The selected input preference
private final InputBindingSetting setting;
private final ArrayList<Float> mPreviousValues = new ArrayList<>();
private int mPrevDeviceId = 0;
private boolean mWaitingForEvent = true;
/**
* Constructor
*
* @param context The current {@link Context}.
* @param setting The Preference to show this dialog for.
*/
public MotionAlertDialog(Context context, InputBindingSetting setting)
{
super(context);
/**
* Constructor
*
* @param context The current {@link Context}.
* @param setting The Preference to show this dialog for.
*/
public MotionAlertDialog(Context context, InputBindingSetting setting)
{
super(context);
this.setting = setting;
}
this.setting = setting;
}
public boolean onKeyEvent(int keyCode, KeyEvent event)
{
Log.debug("[MotionAlertDialog] Received key event: " + event.getAction());
switch (event.getAction())
{
case KeyEvent.ACTION_UP:
if (!ControllerMappingHelper.shouldKeyBeIgnored(event.getDevice(), keyCode))
{
saveKeyInput(event);
}
// Even if we ignore the key, we still consume it. Thus return true regardless.
return true;
public boolean onKeyEvent(int keyCode, KeyEvent event)
{
Log.debug("[MotionAlertDialog] Received key event: " + event.getAction());
switch (event.getAction())
{
case KeyEvent.ACTION_UP:
if (!ControllerMappingHelper.shouldKeyBeIgnored(event.getDevice(), keyCode))
{
saveKeyInput(event);
}
// Even if we ignore the key, we still consume it. Thus return true regardless.
return true;
default:
return false;
}
}
default:
return false;
}
}
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event)
{
// Option to clear by long back is only needed on the TV interface
if (TvUtil.isLeanback(getContext()))
{
if (keyCode == KeyEvent.KEYCODE_BACK)
{
clearBinding();
return true;
}
}
return super.onKeyLongPress(keyCode, event);
}
@Override
public boolean onKeyLongPress(int keyCode, KeyEvent event)
{
// Option to clear by long back is only needed on the TV interface
if (TvUtil.isLeanback(getContext()))
{
if (keyCode == KeyEvent.KEYCODE_BACK)
{
clearBinding();
return true;
}
}
return super.onKeyLongPress(keyCode, event);
}
@Override
public boolean dispatchKeyEvent(KeyEvent event)
{
// Handle this key if we care about it, otherwise pass it down the framework
return onKeyEvent(event.getKeyCode(), event) || super.dispatchKeyEvent(event);
}
@Override
public boolean dispatchKeyEvent(KeyEvent event)
{
// Handle this key if we care about it, otherwise pass it down the framework
return onKeyEvent(event.getKeyCode(), event) || super.dispatchKeyEvent(event);
}
@Override
public boolean dispatchGenericMotionEvent(MotionEvent event)
{
// Handle this event if we care about it, otherwise pass it down the framework
return onMotionEvent(event) || super.dispatchGenericMotionEvent(event);
}
@Override
public boolean dispatchGenericMotionEvent(MotionEvent event)
{
// Handle this event if we care about it, otherwise pass it down the framework
return onMotionEvent(event) || super.dispatchGenericMotionEvent(event);
}
private boolean onMotionEvent(MotionEvent event)
{
if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0)
return false;
if (event.getAction() != MotionEvent.ACTION_MOVE)
return false;
private boolean onMotionEvent(MotionEvent event)
{
if ((event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) == 0)
return false;
if (event.getAction() != MotionEvent.ACTION_MOVE)
return false;
InputDevice input = event.getDevice();
InputDevice input = event.getDevice();
List<InputDevice.MotionRange> motionRanges = input.getMotionRanges();
List<InputDevice.MotionRange> motionRanges = input.getMotionRanges();
if (input.getId() != mPrevDeviceId)
{
mPreviousValues.clear();
}
mPrevDeviceId = input.getId();
boolean firstEvent = mPreviousValues.isEmpty();
if (input.getId() != mPrevDeviceId)
{
mPreviousValues.clear();
}
mPrevDeviceId = input.getId();
boolean firstEvent = mPreviousValues.isEmpty();
int numMovedAxis = 0;
float axisMoveValue = 0.0f;
InputDevice.MotionRange lastMovedRange = null;
char lastMovedDir = '?';
if (mWaitingForEvent)
{
for (int i = 0; i < motionRanges.size(); i++)
{
InputDevice.MotionRange range = motionRanges.get(i);
int axis = range.getAxis();
float origValue = event.getAxisValue(axis);
float value = ControllerMappingHelper.scaleAxis(input, axis, origValue);
if (firstEvent)
{
mPreviousValues.add(value);
}
else
{
float previousValue = mPreviousValues.get(i);
int numMovedAxis = 0;
float axisMoveValue = 0.0f;
InputDevice.MotionRange lastMovedRange = null;
char lastMovedDir = '?';
if (mWaitingForEvent)
{
for (int i = 0; i < motionRanges.size(); i++)
{
InputDevice.MotionRange range = motionRanges.get(i);
int axis = range.getAxis();
float origValue = event.getAxisValue(axis);
float value = ControllerMappingHelper.scaleAxis(input, axis, origValue);
if (firstEvent)
{
mPreviousValues.add(value);
}
else
{
float previousValue = mPreviousValues.get(i);
// Only handle the axes that are not neutral (more than 0.5)
// but ignore any axis that has a constant value (e.g. always 1)
if (Math.abs(value) > 0.5f && value != previousValue)
{
// It is common to have multiple axes with the same physical input. For example,
// shoulder butters are provided as both AXIS_LTRIGGER and AXIS_BRAKE.
// To handle this, we ignore an axis motion that's the exact same as a motion
// we already saw. This way, we ignore axes with two names, but catch the case
// where a joystick is moved in two directions.
// ref: bottom of https://developer.android.com/training/game-controllers/controller-input.html
if (value != axisMoveValue)
{
axisMoveValue = value;
numMovedAxis++;
lastMovedRange = range;
lastMovedDir = value < 0.0f ? '-' : '+';
}
}
// Special case for d-pads (axis value jumps between 0 and 1 without any values
// in between). Without this, the user would need to press the d-pad twice
// due to the first press being caught by the "if (firstEvent)" case further up.
else if (Math.abs(value) < 0.25f && Math.abs(previousValue) > 0.75f)
{
numMovedAxis++;
lastMovedRange = range;
lastMovedDir = previousValue < 0.0f ? '-' : '+';
}
}
// Only handle the axes that are not neutral (more than 0.5)
// but ignore any axis that has a constant value (e.g. always 1)
if (Math.abs(value) > 0.5f && value != previousValue)
{
// It is common to have multiple axes with the same physical input. For example,
// shoulder butters are provided as both AXIS_LTRIGGER and AXIS_BRAKE.
// To handle this, we ignore an axis motion that's the exact same as a motion
// we already saw. This way, we ignore axes with two names, but catch the case
// where a joystick is moved in two directions.
// ref: bottom of https://developer.android.com/training/game-controllers/controller-input.html
if (value != axisMoveValue)
{
axisMoveValue = value;
numMovedAxis++;
lastMovedRange = range;
lastMovedDir = value < 0.0f ? '-' : '+';
}
}
// Special case for d-pads (axis value jumps between 0 and 1 without any values
// in between). Without this, the user would need to press the d-pad twice
// due to the first press being caught by the "if (firstEvent)" case further up.
else if (Math.abs(value) < 0.25f && Math.abs(previousValue) > 0.75f)
{
numMovedAxis++;
lastMovedRange = range;
lastMovedDir = previousValue < 0.0f ? '-' : '+';
}
}
mPreviousValues.set(i, value);
}
mPreviousValues.set(i, value);
}
// If only one axis moved, that's the winner.
if (numMovedAxis == 1)
{
mWaitingForEvent = false;
saveMotionInput(input, lastMovedRange, lastMovedDir);
}
}
// If only one axis moved, that's the winner.
if (numMovedAxis == 1)
{
mWaitingForEvent = false;
saveMotionInput(input, lastMovedRange, lastMovedDir);
}
}
return true;
}
return true;
}
/**
* Saves the provided key input setting both to the INI file (so native code can use it) and as
* an Android preference (so it persists correctly and is human-readable.)
*
* @param keyEvent KeyEvent of this key press.
*/
private void saveKeyInput(KeyEvent keyEvent)
{
InputDevice device = keyEvent.getDevice();
String bindStr = "Device '" + device.getDescriptor() + "'-Button " + keyEvent.getKeyCode();
String uiString = device.getName() + ": Button " + keyEvent.getKeyCode();
/**
* Saves the provided key input setting both to the INI file (so native code can use it) and as
* an Android preference (so it persists correctly and is human-readable.)
*
* @param keyEvent KeyEvent of this key press.
*/
private void saveKeyInput(KeyEvent keyEvent)
{
InputDevice device = keyEvent.getDevice();
String bindStr = "Device '" + device.getDescriptor() + "'-Button " + keyEvent.getKeyCode();
String uiString = device.getName() + ": Button " + keyEvent.getKeyCode();
saveInput(bindStr, uiString);
}
saveInput(bindStr, uiString);
}
/**
* Saves the provided motion input setting both to the INI file (so native code can use it) and as
* an Android preference (so it persists correctly and is human-readable.)
*
* @param device InputDevice from which the input event originated.
* @param motionRange MotionRange of the movement
* @param axisDir Either '-' or '+'
*/
private void saveMotionInput(InputDevice device, InputDevice.MotionRange motionRange, char axisDir)
{
String bindStr = "Device '" + device.getDescriptor() + "'-Axis " + motionRange.getAxis() + axisDir;
String uiString = device.getName() + ": Axis " + motionRange.getAxis() + axisDir;
/**
* Saves the provided motion input setting both to the INI file (so native code can use it) and as
* an Android preference (so it persists correctly and is human-readable.)
*
* @param device InputDevice from which the input event originated.
* @param motionRange MotionRange of the movement
* @param axisDir Either '-' or '+'
*/
private void saveMotionInput(InputDevice device, InputDevice.MotionRange motionRange,
char axisDir)
{
String bindStr =
"Device '" + device.getDescriptor() + "'-Axis " + motionRange.getAxis() + axisDir;
String uiString = device.getName() + ": Axis " + motionRange.getAxis() + axisDir;
saveInput(bindStr, uiString);
}
saveInput(bindStr, uiString);
}
/** Save the input string to settings and SharedPreferences, then dismiss this Dialog. */
private void saveInput(String bind, String ui)
{
setting.setValue(bind);
/**
* Save the input string to settings and SharedPreferences, then dismiss this Dialog.
*/
private void saveInput(String bind, String ui)
{
setting.setValue(bind);
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = preferences.edit();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = preferences.edit();
editor.putString(setting.getKey(), ui);
editor.apply();
editor.putString(setting.getKey(), ui);
editor.apply();
dismiss();
}
dismiss();
}
private void clearBinding()
{
setting.setValue("");
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = preferences.edit();
editor.remove(setting.getKey());
editor.apply();
dismiss();
}
private void clearBinding()
{
setting.setValue("");
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = preferences.edit();
editor.remove(setting.getKey());
editor.apply();
dismiss();
}
}
@@ -2,27 +2,27 @@ package org.dolphinemu.dolphinemu.features.settings.model;
public final class BooleanSetting extends Setting
{
private boolean mValue;
private boolean mValue;
public BooleanSetting(String key, String section, boolean value)
{
super(key, section);
mValue = value;
}
public BooleanSetting(String key, String section, boolean value)
{
super(key, section);
mValue = value;
}
public boolean getValue()
{
return mValue;
}
public boolean getValue()
{
return mValue;
}
public void setValue(boolean value)
{
mValue = value;
}
public void setValue(boolean value)
{
mValue = value;
}
@Override
public String getValueAsString()
{
return mValue ? "True" : "False";
}
@Override
public String getValueAsString()
{
return mValue ? "True" : "False";
}
}
@@ -2,27 +2,27 @@ package org.dolphinemu.dolphinemu.features.settings.model;
public final class FloatSetting extends Setting
{
private float mValue;
private float mValue;
public FloatSetting(String key, String section, float value)
{
super(key, section);
mValue = value;
}
public FloatSetting(String key, String section, float value)
{
super(key, section);
mValue = value;
}
public float getValue()
{
return mValue;
}
public float getValue()
{
return mValue;
}
public void setValue(float value)
{
mValue = value;
}
public void setValue(float value)
{
mValue = value;
}
@Override
public String getValueAsString()
{
return Float.toString(mValue);
}
@Override
public String getValueAsString()
{
return Float.toString(mValue);
}
}
@@ -4,41 +4,41 @@ import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
public final class IntSetting extends Setting
{
private int mValue;
private MenuTag menuTag;
private int mValue;
private MenuTag menuTag;
public IntSetting(String key, String section, int value)
{
super(key, section);
mValue = value;
}
public IntSetting(String key, String section, int value)
{
super(key, section);
mValue = value;
}
public IntSetting(String key, String section, int value, MenuTag menuTag)
{
super(key, section);
mValue = value;
this.menuTag = menuTag;
}
public IntSetting(String key, String section, int value, MenuTag menuTag)
{
super(key, section);
mValue = value;
this.menuTag = menuTag;
}
public int getValue()
{
return mValue;
}
public int getValue()
{
return mValue;
}
public void setValue(int value)
{
mValue = value;
}
public void setValue(int value)
{
mValue = value;
}
@Override
public String getValueAsString()
{
return Integer.toString(mValue);
}
@Override
public String getValueAsString()
{
return Integer.toString(mValue);
}
public MenuTag getMenuTag()
{
return menuTag;
}
public MenuTag getMenuTag()
{
return menuTag;
}
}
@@ -8,42 +8,40 @@ package org.dolphinemu.dolphinemu.features.settings.model;
*/
public abstract class Setting
{
private String mKey;
private String mSection;
private String mKey;
private String mSection;
/**
* Base constructor.
*
* @param key Everything to the left of the = in a line from the ini file.
* @param section The corresponding recent section header; e.g. [Core] or [Enhancements] without the brackets.
*/
public Setting(String key, String section)
{
mKey = key;
mSection = section;
}
/**
* Base constructor.
*
* @param key Everything to the left of the = in a line from the ini file.
* @param section The corresponding recent section header; e.g. [Core] or [Enhancements] without the brackets.
*/
public Setting(String key, String section)
{
mKey = key;
mSection = section;
}
/**
*
* @return The identifier used to write this setting to the ini file.
*/
public String getKey()
{
return mKey;
}
/**
* @return The identifier used to write this setting to the ini file.
*/
public String getKey()
{
return mKey;
}
/**
*
* @return The name of the header under which this Setting should be written in the ini file.
*/
public String getSection()
{
return mSection;
}
/**
* @return The name of the header under which this Setting should be written in the ini file.
*/
public String getSection()
{
return mSection;
}
/**
* @return A representation of this Setting's backing value converted to a String (e.g. for serialization).
*/
public abstract String getValueAsString();
/**
* @return A representation of this Setting's backing value converted to a String (e.g. for serialization).
*/
public abstract String getValueAsString();
}
@@ -8,56 +8,56 @@ import java.util.HashMap;
*/
public final class SettingSection
{
private String mName;
private String mName;
private HashMap<String, Setting> mSettings = new HashMap<>();
private HashMap<String, Setting> mSettings = new HashMap<>();
/**
* Create a new SettingSection with no Settings in it.
*
* @param name The header of this section; e.g. [Core] or [Enhancements] without the brackets.
*/
public SettingSection(String name)
{
mName = name;
}
/**
* Create a new SettingSection with no Settings in it.
*
* @param name The header of this section; e.g. [Core] or [Enhancements] without the brackets.
*/
public SettingSection(String name)
{
mName = name;
}
public String getName()
{
return mName;
}
public String getName()
{
return mName;
}
/**
* Convenience method; inserts a value directly into the backing HashMap.
*
* @param setting The Setting to be inserted.
*/
public void putSetting(Setting setting)
{
mSettings.put(setting.getKey(), setting);
}
/**
* Convenience method; inserts a value directly into the backing HashMap.
*
* @param setting The Setting to be inserted.
*/
public void putSetting(Setting setting)
{
mSettings.put(setting.getKey(), setting);
}
/**
* Convenience method; gets a value directly from the backing HashMap.
*
* @param key Used to retrieve the Setting.
* @return A Setting object (you should probably cast this before using)
*/
public Setting getSetting(String key)
{
return mSettings.get(key);
}
/**
* Convenience method; gets a value directly from the backing HashMap.
*
* @param key Used to retrieve the Setting.
* @return A Setting object (you should probably cast this before using)
*/
public Setting getSetting(String key)
{
return mSettings.get(key);
}
public HashMap<String, Setting> getSettings()
{
return mSettings;
}
public HashMap<String, Setting> getSettings()
{
return mSettings;
}
public void mergeSection(SettingSection settingSection)
{
for (Setting setting : settingSection.mSettings.values())
{
putSetting(setting);
}
}
public void mergeSection(SettingSection settingSection)
{
for (Setting setting : settingSection.mSettings.values())
{
putSetting(setting);
}
}
}
@@ -14,168 +14,174 @@ import java.util.TreeMap;
public class Settings
{
public static final String SECTION_INI_CORE = "Core";
public static final String SECTION_INI_INTERFACE = "Interface";
public static final String SECTION_INI_CORE = "Core";
public static final String SECTION_INI_INTERFACE = "Interface";
public static final String SECTION_GFX_SETTINGS = "Settings";
public static final String SECTION_GFX_ENHANCEMENTS = "Enhancements";
public static final String SECTION_GFX_HACKS = "Hacks";
public static final String SECTION_GFX_SETTINGS = "Settings";
public static final String SECTION_GFX_ENHANCEMENTS = "Enhancements";
public static final String SECTION_GFX_HACKS = "Hacks";
public static final String SECTION_STEREOSCOPY = "Stereoscopy";
public static final String SECTION_STEREOSCOPY = "Stereoscopy";
public static final String SECTION_WIIMOTE = "Wiimote";
public static final String SECTION_WIIMOTE = "Wiimote";
public static final String SECTION_BINDINGS = "Android";
public static final String SECTION_BINDINGS = "Android";
public static final String SECTION_ANALYTICS = "Analytics";
public static final String SECTION_ANALYTICS = "Analytics";
private String gameId;
private String gameId;
private static final Map<String, List<String>> configFileSectionsMap = new HashMap<>();
private static final Map<String, List<String>> configFileSectionsMap = new HashMap<>();
static
static
{
configFileSectionsMap.put(SettingsFile.FILE_NAME_DOLPHIN,
Arrays.asList(SECTION_INI_CORE, SECTION_INI_INTERFACE, SECTION_BINDINGS,
SECTION_ANALYTICS));
configFileSectionsMap.put(SettingsFile.FILE_NAME_GFX,
Arrays.asList(SECTION_GFX_SETTINGS, SECTION_GFX_ENHANCEMENTS, SECTION_GFX_HACKS,
SECTION_STEREOSCOPY));
configFileSectionsMap.put(SettingsFile.FILE_NAME_WIIMOTE,
Arrays.asList(SECTION_WIIMOTE + 1, SECTION_WIIMOTE + 2, SECTION_WIIMOTE + 3,
SECTION_WIIMOTE + 4));
}
/**
* A HashMap<String, SettingSection> that constructs a new SettingSection instead of returning null
* when getting a key not already in the map
*/
public static final class SettingsSectionMap extends HashMap<String, SettingSection>
{
@Override
public SettingSection get(Object key)
{
configFileSectionsMap.put(SettingsFile.FILE_NAME_DOLPHIN, Arrays.asList(SECTION_INI_CORE, SECTION_INI_INTERFACE, SECTION_BINDINGS, SECTION_ANALYTICS));
configFileSectionsMap.put(SettingsFile.FILE_NAME_GFX, Arrays.asList(SECTION_GFX_SETTINGS, SECTION_GFX_ENHANCEMENTS, SECTION_GFX_HACKS, SECTION_STEREOSCOPY));
configFileSectionsMap.put(SettingsFile.FILE_NAME_WIIMOTE, Arrays.asList(SECTION_WIIMOTE + 1, SECTION_WIIMOTE + 2, SECTION_WIIMOTE + 3, SECTION_WIIMOTE + 4));
if (!(key instanceof String))
{
return null;
}
String stringKey = (String) key;
if (!super.containsKey(stringKey))
{
SettingSection section = new SettingSection(stringKey);
super.put(stringKey, section);
return section;
}
return super.get(key);
}
}
private HashMap<String, SettingSection> sections = new Settings.SettingsSectionMap();
public SettingSection getSection(String sectionName)
{
return sections.get(sectionName);
}
public boolean isEmpty()
{
return sections.isEmpty();
}
public HashMap<String, SettingSection> getSections()
{
return sections;
}
public void loadSettings(SettingsActivityView view)
{
sections = new Settings.SettingsSectionMap();
HashSet<String> filesToExclude = new HashSet<>();
if (!TextUtils.isEmpty(gameId))
{
// for per-game settings, don't load the WiiMoteNew.ini settings
filesToExclude.add(SettingsFile.FILE_NAME_WIIMOTE);
}
/**
* A HashMap<String, SettingSection> that constructs a new SettingSection instead of returning null
* when getting a key not already in the map
*/
public static final class SettingsSectionMap extends HashMap<String, SettingSection>
loadDolphinSettings(view, filesToExclude);
if (!TextUtils.isEmpty(gameId))
{
@Override
public SettingSection get(Object key)
loadGenericGameSettings(gameId, view);
loadCustomGameSettings(gameId, view);
}
}
private void loadDolphinSettings(SettingsActivityView view, HashSet<String> filesToExclude)
{
for (Map.Entry<String, List<String>> entry : configFileSectionsMap.entrySet())
{
String fileName = entry.getKey();
if (filesToExclude == null || !filesToExclude.contains(fileName))
{
sections.putAll(SettingsFile.readFile(fileName, view));
}
}
}
private void loadGenericGameSettings(String gameId, SettingsActivityView view)
{
// generic game settings
mergeSections(SettingsFile.readGenericGameSettings(gameId, view));
mergeSections(SettingsFile.readGenericGameSettingsForAllRegions(gameId, view));
}
private void loadCustomGameSettings(String gameId, SettingsActivityView view)
{
// custom game settings
mergeSections(SettingsFile.readCustomGameSettings(gameId, view));
}
private void mergeSections(HashMap<String, SettingSection> updatedSections)
{
for (Map.Entry<String, SettingSection> entry : updatedSections.entrySet())
{
if (sections.containsKey(entry.getKey()))
{
SettingSection originalSection = sections.get(entry.getKey());
SettingSection updatedSection = entry.getValue();
originalSection.mergeSection(updatedSection);
}
else
{
sections.put(entry.getKey(), entry.getValue());
}
}
}
public void loadSettings(String gameId, SettingsActivityView view)
{
this.gameId = gameId;
loadSettings(view);
}
public void saveSettings(SettingsActivityView view)
{
if (TextUtils.isEmpty(gameId))
{
view.showToastMessage("Saved settings to INI files");
for (Map.Entry<String, List<String>> entry : configFileSectionsMap.entrySet())
{
String fileName = entry.getKey();
List<String> sectionNames = entry.getValue();
TreeMap<String, SettingSection> iniSections = new TreeMap<>();
for (String section : sectionNames)
{
if (!(key instanceof String))
{
return null;
}
String stringKey = (String) key;
if (!super.containsKey(stringKey))
{
SettingSection section = new SettingSection(stringKey);
super.put(stringKey, section);
return section;
}
return super.get(key);
}
}
private HashMap<String, SettingSection> sections = new Settings.SettingsSectionMap();
public SettingSection getSection(String sectionName)
{
return sections.get(sectionName);
}
public boolean isEmpty()
{
return sections.isEmpty();
}
public HashMap<String, SettingSection> getSections()
{
return sections;
}
public void loadSettings(SettingsActivityView view)
{
sections = new Settings.SettingsSectionMap();
HashSet<String> filesToExclude = new HashSet<>();
if (!TextUtils.isEmpty(gameId))
{
// for per-game settings, don't load the WiiMoteNew.ini settings
filesToExclude.add(SettingsFile.FILE_NAME_WIIMOTE);
iniSections.put(section, sections.get(section));
}
loadDolphinSettings(view, filesToExclude);
if (!TextUtils.isEmpty(gameId))
{
loadGenericGameSettings(gameId, view);
loadCustomGameSettings(gameId, view);
}
SettingsFile.saveFile(fileName, iniSections, view);
}
}
private void loadDolphinSettings(SettingsActivityView view, HashSet<String> filesToExclude)
else
{
for (Map.Entry<String, List<String>> entry : configFileSectionsMap.entrySet())
{
String fileName = entry.getKey();
if(filesToExclude == null || !filesToExclude.contains(fileName))
{
sections.putAll(SettingsFile.readFile(fileName, view));
}
}
// custom game settings
view.showToastMessage("Saved settings for " + gameId);
SettingsFile.saveCustomGameSettings(gameId, sections);
}
private void loadGenericGameSettings(String gameId, SettingsActivityView view)
{
// generic game settings
mergeSections(SettingsFile.readGenericGameSettings(gameId, view));
mergeSections(SettingsFile.readGenericGameSettingsForAllRegions(gameId, view));
}
private void loadCustomGameSettings(String gameId, SettingsActivityView view)
{
// custom game settings
mergeSections(SettingsFile.readCustomGameSettings(gameId, view));
}
private void mergeSections(HashMap<String, SettingSection> updatedSections)
{
for (Map.Entry<String, SettingSection> entry : updatedSections.entrySet())
{
if (sections.containsKey(entry.getKey()))
{
SettingSection originalSection = sections.get(entry.getKey());
SettingSection updatedSection = entry.getValue();
originalSection.mergeSection(updatedSection);
}
else
{
sections.put(entry.getKey(), entry.getValue());
}
}
}
public void loadSettings(String gameId, SettingsActivityView view)
{
this.gameId = gameId;
loadSettings(view);
}
public void saveSettings(SettingsActivityView view)
{
if (TextUtils.isEmpty(gameId))
{
view.showToastMessage("Saved settings to INI files");
for (Map.Entry<String, List<String>> entry : configFileSectionsMap.entrySet())
{
String fileName = entry.getKey();
List<String> sectionNames = entry.getValue();
TreeMap<String, SettingSection> iniSections = new TreeMap<>();
for (String section : sectionNames)
{
iniSections.put(section, sections.get(section));
}
SettingsFile.saveFile(fileName, iniSections, view);
}
}
else
{
// custom game settings
view.showToastMessage("Saved settings for " + gameId);
SettingsFile.saveCustomGameSettings(gameId, sections);
}
}
}
}
@@ -2,27 +2,27 @@ package org.dolphinemu.dolphinemu.features.settings.model;
public final class StringSetting extends Setting
{
private String mValue;
private String mValue;
public StringSetting(String key, String section, String value)
{
super(key, section);
mValue = value;
}
public StringSetting(String key, String section, String value)
{
super(key, section);
mValue = value;
}
public String getValue()
{
return mValue;
}
public String getValue()
{
return mValue;
}
public void setValue(String value)
{
mValue = value;
}
public void setValue(String value)
{
mValue = value;
}
@Override
public String getValueAsString()
{
return mValue;
}
@Override
public String getValueAsString()
{
return mValue;
}
}

Some files were not shown because too many files have changed in this diff Show More