diff --git a/Source/Android/app/src/main/AndroidManifest.xml b/Source/Android/app/src/main/AndroidManifest.xml index adfda3d0ce..0d83b3a37d 100644 --- a/Source/Android/app/src/main/AndroidManifest.xml +++ b/Source/Android/app/src/main/AndroidManifest.xml @@ -27,7 +27,7 @@ android:banner="@drawable/banner_tv"> diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java deleted file mode 100644 index 5dc3bbd983..0000000000 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/MainActivity.java +++ /dev/null @@ -1,173 +0,0 @@ -package org.dolphinemu.dolphinemu.activities; - -import android.content.Intent; -import android.content.SharedPreferences; -import android.database.Cursor; -import android.os.Bundle; -import android.preference.PreferenceManager; -import android.support.annotation.Nullable; -import android.support.design.widget.FloatingActionButton; -import android.support.design.widget.TabLayout; -import android.support.v4.view.ViewPager; -import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.Toolbar; -import android.util.Log; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; - -import org.dolphinemu.dolphinemu.NativeLibrary; -import org.dolphinemu.dolphinemu.R; -import org.dolphinemu.dolphinemu.adapters.PlatformPagerAdapter; -import org.dolphinemu.dolphinemu.fragments.PlatformGamesFragment; -import org.dolphinemu.dolphinemu.model.Game; -import org.dolphinemu.dolphinemu.model.GameDatabase; -import org.dolphinemu.dolphinemu.model.GameProvider; -import org.dolphinemu.dolphinemu.services.AssetCopyService; -import org.dolphinemu.dolphinemu.utils.StartupHandler; - -/** - * The main Activity of the Lollipop style UI. Manages several PlatformGamesFragments, which - * individually display a grid of available games for each Fragment, in a tabbed layout. - */ -public final class MainActivity extends AppCompatActivity -{ - public static final int REQUEST_ADD_DIRECTORY = 1; - public static final int REQUEST_EMULATE_GAME = 2; - - private ViewPager mViewPager; - private PlatformPagerAdapter mPlatformPagerAdapter; - - @Override - protected void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - // Set up the Toolbar. - Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_main); - setSupportActionBar(toolbar); - - // TODO Rather than calling into native code, this should use the commented line below. - // String versionName = BuildConfig.VERSION_NAME; - String versionName = NativeLibrary.GetVersionString(); - toolbar.setSubtitle(versionName); - - // Set up the Tab bar. - mViewPager = (ViewPager) findViewById(R.id.pager_platforms); - - mPlatformPagerAdapter = new PlatformPagerAdapter(getFragmentManager(), this); - mViewPager.setAdapter(mPlatformPagerAdapter); - - TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs_platforms); - tabLayout.setupWithViewPager(mViewPager); - - // Set up the FAB. - FloatingActionButton buttonAddDirectory = (FloatingActionButton) findViewById(R.id.button_add_directory); - buttonAddDirectory.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View view) - { - Intent fileChooser = new Intent(MainActivity.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) - StartupHandler.HandleInit(this); - } - - /** - * 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) - { - switch (requestCode) - { - case REQUEST_ADD_DIRECTORY: - // 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) - { - refreshFragment(); - } - } - break; - - case REQUEST_EMULATE_GAME: - // Invalidate Picasso image so that the new screenshot is animated in. - PlatformGamesFragment fragment = getPlatformFragment(mViewPager.getCurrentItem()); - - if (fragment != null) - { - fragment.refreshScreenshotAtPosition(resultCode); - } - break; - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) - { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.menu_game_grid, menu); - return true; - } - - /** - * Called by the framework whenever any actionbar/toolbar icon is clicked. - * - * @param item The icon that was clicked on. - * @return True if the event was handled, false to bubble it up to the OS. - */ - @Override - public boolean onOptionsItemSelected(MenuItem item) - { - switch (item.getItemId()) - { - case R.id.menu_settings: - // Launch the Settings Actvity. - Intent settings = new Intent(this, SettingsActivity.class); - startActivity(settings); - return true; - - case R.id.menu_refresh: - getContentResolver().insert(GameProvider.URI_REFRESH, null); - refreshFragment(); - - return true; - } - - return false; - } - - public void refreshFragment() - { - PlatformGamesFragment fragment = getPlatformFragment(mViewPager.getCurrentItem()); - if (fragment != null) - { - fragment.refresh(); - } - } - - @Nullable - public PlatformGamesFragment getPlatformFragment(int platform) - { - String fragmentTag = "android:switcher:" + mViewPager.getId() + ":" + platform; - - return (PlatformGamesFragment) getFragmentManager().findFragmentByTag(fragmentTag); - } -} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java index a01e080549..c772451954 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/TvMainActivity.java @@ -4,10 +4,8 @@ import android.app.Activity; import android.app.ActivityOptions; import android.app.FragmentManager; import android.content.Intent; -import android.content.SharedPreferences; import android.database.Cursor; import android.os.Bundle; -import android.preference.PreferenceManager; import android.support.v17.leanback.app.BrowseFragment; import android.support.v17.leanback.database.CursorMapper; import android.support.v17.leanback.widget.ArrayObjectAdapter; @@ -21,7 +19,6 @@ import android.support.v17.leanback.widget.Row; import android.support.v17.leanback.widget.RowPresenter; import android.widget.Toast; -import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.adapters.GameRowPresenter; import org.dolphinemu.dolphinemu.adapters.SettingsRowPresenter; @@ -29,7 +26,8 @@ import org.dolphinemu.dolphinemu.model.Game; import org.dolphinemu.dolphinemu.model.GameDatabase; import org.dolphinemu.dolphinemu.model.GameProvider; import org.dolphinemu.dolphinemu.model.TvSettingsItem; -import org.dolphinemu.dolphinemu.services.AssetCopyService; +import org.dolphinemu.dolphinemu.ui.main.MainActivity; +import org.dolphinemu.dolphinemu.ui.main.MainPresenter; import org.dolphinemu.dolphinemu.utils.StartupHandler; import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; @@ -88,7 +86,7 @@ public final class TvMainActivity extends Activity Intent fileChooser = new Intent(TvMainActivity.this, AddDirectoryActivity.class); // The second argument to this method is read below in onActivityResult(). - startActivityForResult(fileChooser, MainActivity.REQUEST_ADD_DIRECTORY); + startActivityForResult(fileChooser, MainPresenter.REQUEST_ADD_DIRECTORY); break; @@ -134,13 +132,13 @@ public final class TvMainActivity extends Activity { switch (requestCode) { - case MainActivity.REQUEST_ADD_DIRECTORY: + case MainPresenter.REQUEST_ADD_DIRECTORY: // 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 == MainActivity.REQUEST_ADD_DIRECTORY) + if (requestCode == MainPresenter.REQUEST_ADD_DIRECTORY) { // TODO Let the Activity know the data is refreshed in some other, better way. recreate(); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java index e74bd6f96d..2a0b0783c0 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java @@ -17,9 +17,10 @@ import com.squareup.picasso.Picasso; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.activities.EmulationActivity; -import org.dolphinemu.dolphinemu.activities.MainActivity; +import org.dolphinemu.dolphinemu.ui.main.MainActivity; import org.dolphinemu.dolphinemu.dialogs.GameDetailsDialog; import org.dolphinemu.dolphinemu.model.GameDatabase; +import org.dolphinemu.dolphinemu.ui.main.MainPresenter; import org.dolphinemu.dolphinemu.viewholders.GameViewHolder; /** @@ -231,7 +232,7 @@ public final class GameAdapter extends RecyclerView.Adapter impl "image_game_screenshot"); ((Activity) view.getContext()).startActivityForResult(intent, - MainActivity.REQUEST_EMULATE_GAME, + MainPresenter.REQUEST_EMULATE_GAME, options.toBundle()); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java new file mode 100644 index 0000000000..ac2bfe5258 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java @@ -0,0 +1,174 @@ +package org.dolphinemu.dolphinemu.ui.main; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.design.widget.FloatingActionButton; +import android.support.design.widget.TabLayout; +import android.support.v4.view.ViewPager; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; + +import org.dolphinemu.dolphinemu.NativeLibrary; +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.activities.AddDirectoryActivity; +import org.dolphinemu.dolphinemu.activities.SettingsActivity; +import org.dolphinemu.dolphinemu.adapters.PlatformPagerAdapter; +import org.dolphinemu.dolphinemu.fragments.PlatformGamesFragment; +import org.dolphinemu.dolphinemu.model.GameProvider; +import org.dolphinemu.dolphinemu.utils.StartupHandler; + +/** + * The main Activity of the Lollipop style UI. Manages several PlatformGamesFragments, which + * individually display a grid of available games for each Fragment, in a tabbed layout. + */ +public final class MainActivity extends AppCompatActivity implements MainView +{ + private ViewPager mViewPager; + private Toolbar mToolbar; + private TabLayout mTabLayout; + private FloatingActionButton mFab; + + private MainPresenter mPresenter = new MainPresenter(this); + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + findViews(); + + setSupportActionBar(mToolbar); + + PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter(getFragmentManager(), this); + + mViewPager.setAdapter(platformPagerAdapter); + mTabLayout.setupWithViewPager(mViewPager); + + // Set up the FAB. + mFab.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(View view) + { + mPresenter.onFabClick(); + } + }); + + mPresenter.onCreate(); + + // Stuff in this block only happens when this activity is newly created (i.e. not a rotation) + // TODO Split some of this stuff into Application.onCreate() + if (savedInstanceState == null) + StartupHandler.HandleInit(this); + } + + // TODO: Replace with a ButterKnife injection. + private void findViews() + { + mToolbar = (Toolbar) findViewById(R.id.toolbar_main); + mViewPager = (ViewPager) findViewById(R.id.pager_platforms); + mTabLayout = (TabLayout) findViewById(R.id.tabs_platforms); + mFab = (FloatingActionButton) findViewById(R.id.button_add_directory); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) + { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.menu_game_grid, menu); + return true; + } + + /** + * MainView + */ + + @Override + public void setSubtitle(String subtitle) + { + mToolbar.setSubtitle(subtitle); + } + + @Override + public void refresh() + { + getContentResolver().insert(GameProvider.URI_REFRESH, null); + refreshFragment(); + } + + @Override + public void refreshFragmentScreenshot(int fragmentPosition) + { + // Invalidate Picasso image so that the new screenshot is animated in. + PlatformGamesFragment fragment = getPlatformFragment(mViewPager.getCurrentItem()); + + if (fragment != null) + { + fragment.refreshScreenshotAtPosition(fragmentPosition); + } + } + + @Override + public void launchSettingsActivity() + { + Intent settings = new Intent(this, SettingsActivity.class); + startActivity(settings); + } + + @Override + public void launchFileListActivity() + { + Intent fileChooser = new Intent(MainActivity.this, AddDirectoryActivity.class); + + // The second argument to this method is read below in onActivityResult(). + startActivityForResult(fileChooser, MainPresenter.REQUEST_ADD_DIRECTORY); + } + + /** + * 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) + { + mPresenter.handleActivityResult(requestCode, resultCode); + } + + /** + * Called by the framework whenever any actionbar/toolbar icon is clicked. + * + * @param item The icon that was clicked on. + * @return True if the event was handled, false to bubble it up to the OS. + */ + @Override + public boolean onOptionsItemSelected(MenuItem item) + { + return mPresenter.handleOptionSelection(item.getItemId()); + } + + private void refreshFragment() + { + PlatformGamesFragment fragment = getPlatformFragment(mViewPager.getCurrentItem()); + if (fragment != null) + { + fragment.refresh(); + } + } + + @Nullable + private PlatformGamesFragment getPlatformFragment(int platform) + { + String fragmentTag = "android:switcher:" + mViewPager.getId() + ":" + platform; + + return (PlatformGamesFragment) getFragmentManager().findFragmentByTag(fragmentTag); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java new file mode 100644 index 0000000000..992b242d88 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java @@ -0,0 +1,68 @@ +package org.dolphinemu.dolphinemu.ui.main; + + +import android.content.Intent; + +import org.dolphinemu.dolphinemu.NativeLibrary; +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.activities.SettingsActivity; +import org.dolphinemu.dolphinemu.fragments.PlatformGamesFragment; +import org.dolphinemu.dolphinemu.model.GameProvider; +import org.dolphinemu.dolphinemu.ui.main.MainView; + +public class MainPresenter +{ + public static final int REQUEST_ADD_DIRECTORY = 1; + public static final int REQUEST_EMULATE_GAME = 2; + + private final MainView mView; + + public MainPresenter(MainView view) + { + mView = view; + } + + public void onCreate() + { + // TODO Rather than calling into native code, this should use the commented line below. + // String versionName = BuildConfig.VERSION_NAME; + String versionName = NativeLibrary.GetVersionString(); + mView.setSubtitle(versionName); + } + + public void onFabClick() { + mView.launchFileListActivity(); + } + + public boolean handleOptionSelection(int itemId) { + switch (itemId) + { + case R.id.menu_settings: + mView.launchSettingsActivity(); + return true; + + case R.id.menu_refresh: + mView.refresh(); + return true; + } + + return false; + } + + public void handleActivityResult(int requestCode, int resultCode) { + switch (requestCode) + { + case REQUEST_ADD_DIRECTORY: + // If the user picked a file, as opposed to just backing out. + if (resultCode == MainActivity.RESULT_OK) + { + mView.refresh(); + } + break; + + case REQUEST_EMULATE_GAME: + mView.refreshFragmentScreenshot(resultCode); + break; + } + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainView.java new file mode 100644 index 0000000000..4c8b26f306 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainView.java @@ -0,0 +1,15 @@ +package org.dolphinemu.dolphinemu.ui.main; + + +public interface MainView +{ + void setSubtitle(String subtitle); + + void refresh(); + + void refreshFragmentScreenshot(int fragmentPosition); + + void launchSettingsActivity(); + + void launchFileListActivity(); +}