From 2434c2db5975db2dec53541ced7184144e15f03f Mon Sep 17 00:00:00 2001 From: Charles Lombardo Date: Sat, 3 Jun 2023 20:40:38 -0400 Subject: [PATCH] Android: Convert TvMainActivity to Kotlin --- .../dolphinemu/ui/main/TvMainActivity.java | 418 ------------------ .../dolphinemu/ui/main/TvMainActivity.kt | 370 ++++++++++++++++ 2 files changed, 370 insertions(+), 418 deletions(-) delete mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.kt diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java deleted file mode 100644 index 2da1b8591d..0000000000 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java +++ /dev/null @@ -1,418 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -package org.dolphinemu.dolphinemu.ui.main; - -import android.content.Intent; -import android.content.pm.PackageManager; -import android.net.Uri; -import android.os.Bundle; - -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; -import androidx.core.splashscreen.SplashScreen; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; -import androidx.leanback.app.BrowseSupportFragment; -import androidx.leanback.widget.ArrayObjectAdapter; -import androidx.leanback.widget.HeaderItem; -import androidx.leanback.widget.ListRow; -import androidx.leanback.widget.ListRowPresenter; -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; - -import org.dolphinemu.dolphinemu.fragments.GridOptionDialogFragment; -import org.dolphinemu.dolphinemu.R; -import org.dolphinemu.dolphinemu.activities.EmulationActivity; -import org.dolphinemu.dolphinemu.adapters.GameRowPresenter; -import org.dolphinemu.dolphinemu.adapters.SettingsRowPresenter; -import org.dolphinemu.dolphinemu.databinding.ActivityTvMainBinding; -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.model.TvSettingsItem; -import org.dolphinemu.dolphinemu.services.GameFileCacheManager; -import org.dolphinemu.dolphinemu.ui.platform.Platform; -import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; -import org.dolphinemu.dolphinemu.utils.FileBrowserHelper; -import org.dolphinemu.dolphinemu.utils.PermissionsHandler; -import org.dolphinemu.dolphinemu.utils.StartupHandler; -import org.dolphinemu.dolphinemu.utils.TvUtil; -import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; - -import java.util.ArrayList; -import java.util.Collection; - -public final class TvMainActivity extends FragmentActivity - implements MainView, SwipeRefreshLayout.OnRefreshListener -{ - private final MainPresenter mPresenter = new MainPresenter(this, this); - - private SwipeRefreshLayout mSwipeRefresh; - - private BrowseSupportFragment mBrowseFragment; - - private final ArrayList mGameRows = new ArrayList<>(); - - private ActivityTvMainBinding mBinding; - - @Override - protected void onCreate(Bundle savedInstanceState) - { - SplashScreen splashScreen = SplashScreen.installSplashScreen(this); - splashScreen.setKeepOnScreenCondition( - () -> !DirectoryInitialization.areDolphinDirectoriesReady()); - - super.onCreate(savedInstanceState); - mBinding = ActivityTvMainBinding.inflate(getLayoutInflater()); - setContentView(mBinding.getRoot()); - - setupUI(); - - mPresenter.onCreate(); - - // Stuff in this block only happens when this activity is newly created (i.e. not a rotation) - if (savedInstanceState == null) - { - StartupHandler.HandleInit(this); - } - } - - @Override - protected void onResume() - { - super.onResume(); - - if (DirectoryInitialization.shouldStart(this)) - { - DirectoryInitialization.start(this); - GameFileCacheManager.startLoad(); - } - - mPresenter.onResume(); - } - - @Override - protected void onDestroy() - { - super.onDestroy(); - mPresenter.onDestroy(); - } - - @Override - protected void onStart() - { - super.onStart(); - StartupHandler.checkSessionReset(this); - } - - @Override - protected void onStop() - { - super.onStop(); - - if (isChangingConfigurations()) - { - MainPresenter.skipRescanningLibrary(); - } - - StartupHandler.setSessionTime(this); - } - - void setupUI() - { - mSwipeRefresh = mBinding.swipeRefresh; - - mSwipeRefresh.setOnRefreshListener(this); - - setRefreshing(GameFileCacheManager.isLoadingOrRescanning()); - - final FragmentManager fragmentManager = getSupportFragmentManager(); - mBrowseFragment = new BrowseSupportFragment(); - fragmentManager - .beginTransaction() - .add(R.id.content, mBrowseFragment, "BrowseFragment") - .commit(); - - // Set display parameters for the BrowseFragment - mBrowseFragment.setHeadersState(BrowseSupportFragment.HEADERS_ENABLED); - mBrowseFragment.setBrandColor(ContextCompat.getColor(this, R.color.dolphin_blue)); - buildRowsAdapter(); - - mBrowseFragment.setOnItemViewClickedListener( - (itemViewHolder, item, rowViewHolder, row) -> - { - // Special case: user clicked on a settings row item. - if (item instanceof TvSettingsItem) - { - TvSettingsItem settingsItem = (TvSettingsItem) item; - mPresenter.handleOptionSelection(settingsItem.getItemId(), this); - } - else - { - TvGameViewHolder holder = (TvGameViewHolder) itemViewHolder; - - // Start the emulation activity and send the path of the clicked ISO to it. - String[] paths = GameFileCacheManager.findSecondDiscAndGetPaths(holder.gameFile); - EmulationActivity.launch(TvMainActivity.this, paths, false); - } - }); - } - - /** - * MainView - */ - - @Override - public void setVersionString(String version) - { - mBrowseFragment.setTitle(version); - } - - @Override - public void launchSettingsActivity(MenuTag menuTag) - { - SettingsActivity.launch(this, menuTag); - } - - @Override - public void launchFileListActivity() - { - if (DirectoryInitialization.preferOldFolderPicker(this)) - { - FileBrowserHelper.openDirectoryPicker(this, FileBrowserHelper.GAME_EXTENSIONS); - } - else - { - Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); - startActivityForResult(intent, MainPresenter.REQUEST_DIRECTORY); - } - } - - @Override - public void launchOpenFileActivity(int requestCode) - { - Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); - intent.addCategory(Intent.CATEGORY_OPENABLE); - intent.setType("*/*"); - startActivityForResult(intent, requestCode); - } - - /** - * Shows or hides the loading indicator. - */ - @Override - public void setRefreshing(boolean refreshing) - { - mSwipeRefresh.setRefreshing(refreshing); - } - - @Override - public void showGames() - { - // Kicks off the program services to update all channels - TvUtil.updateAllChannels(getApplicationContext()); - - buildRowsAdapter(); - } - - @Override - public void reloadGrid() - { - for (ArrayObjectAdapter row : mGameRows) - { - row.notifyArrayItemRangeChanged(0, row.size()); - } - } - - @Override - public void showGridOptions() - { - new GridOptionDialogFragment().show(getSupportFragmentManager(), "gridOptions"); - } - - /** - * 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) - { - super.onActivityResult(requestCode, resultCode, result); - - // If the user picked a file, as opposed to just backing out. - if (resultCode == RESULT_OK) - { - Uri uri = result.getData(); - switch (requestCode) - { - case MainPresenter.REQUEST_DIRECTORY: - if (DirectoryInitialization.preferOldFolderPicker(this)) - { - mPresenter.onDirectorySelected(FileBrowserHelper.getSelectedPath(result)); - } - else - { - mPresenter.onDirectorySelected(result); - } - break; - - case MainPresenter.REQUEST_GAME_FILE: - FileBrowserHelper.runAfterExtensionCheck(this, uri, - FileBrowserHelper.GAME_LIKE_EXTENSIONS, - () -> EmulationActivity.launch(this, result.getData().toString(), false)); - break; - - case MainPresenter.REQUEST_WAD_FILE: - FileBrowserHelper.runAfterExtensionCheck(this, uri, FileBrowserHelper.WAD_EXTENSION, - () -> mPresenter.installWAD(result.getData().toString())); - break; - - case MainPresenter.REQUEST_WII_SAVE_FILE: - FileBrowserHelper.runAfterExtensionCheck(this, uri, FileBrowserHelper.BIN_EXTENSION, - () -> mPresenter.importWiiSave(result.getData().toString())); - break; - - case MainPresenter.REQUEST_NAND_BIN_FILE: - FileBrowserHelper.runAfterExtensionCheck(this, uri, FileBrowserHelper.BIN_EXTENSION, - () -> mPresenter.importNANDBin(result.getData().toString())); - break; - } - } - else - { - MainPresenter.skipRescanningLibrary(); - } - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, - @NonNull int[] grantResults) - { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - - if (requestCode == PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION) - { - if (grantResults[0] == PackageManager.PERMISSION_DENIED) - { - PermissionsHandler.setWritePermissionDenied(); - } - - DirectoryInitialization.start(this); - GameFileCacheManager.startLoad(); - } - } - - /** - * Called when the user requests a refresh by swiping down. - */ - @Override - public void onRefresh() - { - setRefreshing(true); - GameFileCacheManager.startRescan(); - } - - private void buildRowsAdapter() - { - ArrayObjectAdapter rowsAdapter = new ArrayObjectAdapter(new ListRowPresenter()); - mGameRows.clear(); - - if (!DirectoryInitialization.isWaitingForWriteAccess(this)) - { - GameFileCacheManager.startLoad(); - } - - for (Platform platform : Platform.values()) - { - ListRow row = buildGamesRow(platform, GameFileCacheManager.getGameFilesForPlatform(platform)); - - // Add row to the adapter only if it is not empty. - if (row != null) - { - rowsAdapter.add(row); - } - } - - rowsAdapter.add(buildSettingsRow()); - - mBrowseFragment.setAdapter(rowsAdapter); - } - - private ListRow buildGamesRow(Platform platform, Collection gameFiles) - { - // If there are no games, don't return a Row. - if (gameFiles.size() == 0) - { - return null; - } - - // Create an adapter for this row. - ArrayObjectAdapter row = new ArrayObjectAdapter(new GameRowPresenter(this)); - row.addAll(0, gameFiles); - - // Keep a reference to the row in case we need to refresh it. - mGameRows.add(row); - - // Create a header for this row. - HeaderItem header = new HeaderItem(platform.toInt(), getString(platform.getHeaderName())); - - // Create the row, passing it the filled adapter and the header, and give it to the master adapter. - return new ListRow(header, row); - } - - private ListRow buildSettingsRow() - { - ArrayObjectAdapter rowItems = new ArrayObjectAdapter(new SettingsRowPresenter()); - - rowItems.add(new TvSettingsItem(R.id.menu_settings, - R.drawable.ic_settings_tv, - R.string.grid_menu_settings)); - - rowItems.add(new TvSettingsItem(R.id.button_add_directory, - R.drawable.ic_add_tv, - R.string.add_directory_title)); - - rowItems.add(new TvSettingsItem(R.id.menu_grid_options, - R.drawable.ic_list_tv, - R.string.grid_menu_grid_options)); - - rowItems.add(new TvSettingsItem(R.id.menu_refresh, - R.drawable.ic_refresh_tv, - R.string.grid_menu_refresh)); - - rowItems.add(new TvSettingsItem(R.id.menu_open_file, - R.drawable.ic_play_tv, - R.string.grid_menu_open_file)); - - rowItems.add(new TvSettingsItem(R.id.menu_install_wad, - R.drawable.ic_folder_tv, - R.string.grid_menu_install_wad)); - - rowItems.add(new TvSettingsItem(R.id.menu_load_wii_system_menu, - R.drawable.ic_folder_tv, - R.string.grid_menu_load_wii_system_menu)); - - rowItems.add(new TvSettingsItem(R.id.menu_import_wii_save, - R.drawable.ic_folder_tv, - R.string.grid_menu_import_wii_save)); - - rowItems.add(new TvSettingsItem(R.id.menu_import_nand_backup, - R.drawable.ic_folder_tv, - R.string.grid_menu_import_nand_backup)); - - rowItems.add(new TvSettingsItem(R.id.menu_online_system_update, - R.drawable.ic_folder_tv, - R.string.grid_menu_online_system_update)); - - rowItems.add(new TvSettingsItem(R.id.menu_about, - R.drawable.ic_info_tv, - R.string.grid_menu_about)); - - // Create a header for this row. - HeaderItem header = new HeaderItem(R.string.settings, getString(R.string.settings)); - - return new ListRow(header, rowItems); - } -} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.kt new file mode 100644 index 0000000000..79ec2f2943 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.kt @@ -0,0 +1,370 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +package org.dolphinemu.dolphinemu.ui.main + +import android.content.Intent +import android.content.pm.PackageManager +import android.os.Bundle +import androidx.core.content.ContextCompat +import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen +import androidx.fragment.app.FragmentActivity +import androidx.leanback.app.BrowseSupportFragment +import androidx.leanback.widget.ArrayObjectAdapter +import androidx.leanback.widget.HeaderItem +import androidx.leanback.widget.ListRow +import androidx.leanback.widget.ListRowPresenter +import androidx.leanback.widget.OnItemViewClickedListener +import androidx.leanback.widget.Presenter +import androidx.leanback.widget.Row +import androidx.leanback.widget.RowPresenter +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener +import org.dolphinemu.dolphinemu.R +import org.dolphinemu.dolphinemu.activities.EmulationActivity +import org.dolphinemu.dolphinemu.adapters.GameRowPresenter +import org.dolphinemu.dolphinemu.adapters.SettingsRowPresenter +import org.dolphinemu.dolphinemu.databinding.ActivityTvMainBinding +import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag +import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity +import org.dolphinemu.dolphinemu.fragments.GridOptionDialogFragment +import org.dolphinemu.dolphinemu.model.GameFile +import org.dolphinemu.dolphinemu.model.TvSettingsItem +import org.dolphinemu.dolphinemu.services.GameFileCacheManager +import org.dolphinemu.dolphinemu.ui.platform.Platform +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization +import org.dolphinemu.dolphinemu.utils.FileBrowserHelper +import org.dolphinemu.dolphinemu.utils.PermissionsHandler +import org.dolphinemu.dolphinemu.utils.StartupHandler +import org.dolphinemu.dolphinemu.utils.TvUtil +import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder + +class TvMainActivity : FragmentActivity(), MainView, OnRefreshListener { + private val presenter = MainPresenter(this, this) + + private var swipeRefresh: SwipeRefreshLayout? = null + + private var browseFragment: BrowseSupportFragment? = null + + private val gameRows = ArrayList() + + private lateinit var binding: ActivityTvMainBinding + + override fun onCreate(savedInstanceState: Bundle?) { + installSplashScreen().setKeepOnScreenCondition { !DirectoryInitialization.areDolphinDirectoriesReady() } + + super.onCreate(savedInstanceState) + binding = ActivityTvMainBinding.inflate(layoutInflater) + setContentView(binding.root) + + setupUI() + + presenter.onCreate() + + // Stuff in this block only happens when this activity is newly created (i.e. not a rotation) + if (savedInstanceState == null) { + StartupHandler.HandleInit(this) + } + } + + override fun onResume() { + super.onResume() + if (DirectoryInitialization.shouldStart(this)) { + DirectoryInitialization.start(this) + GameFileCacheManager.startLoad() + } + + presenter.onResume() + } + + override fun onStart() { + super.onStart() + StartupHandler.checkSessionReset(this) + } + + override fun onStop() { + super.onStop() + if (isChangingConfigurations) { + MainPresenter.skipRescanningLibrary() + } + StartupHandler.setSessionTime(this) + } + + private fun setupUI() { + swipeRefresh = binding.swipeRefresh + swipeRefresh!!.setOnRefreshListener(this) + setRefreshing(GameFileCacheManager.isLoadingOrRescanning()) + + browseFragment = BrowseSupportFragment() + supportFragmentManager + .beginTransaction() + .add(R.id.content, browseFragment!!, "BrowseFragment") + .commit() + + // Set display parameters for the BrowseFragment + browseFragment?.headersState = BrowseSupportFragment.HEADERS_ENABLED + browseFragment?.brandColor = ContextCompat.getColor(this, R.color.dolphin_blue) + buildRowsAdapter() + + browseFragment?.onItemViewClickedListener = + OnItemViewClickedListener { itemViewHolder: Presenter.ViewHolder, item: Any?, _: RowPresenter.ViewHolder?, _: Row? -> + // Special case: user clicked on a settings row item. + if (item is TvSettingsItem) { + presenter.handleOptionSelection(item.itemId, this) + } else { + val holder = itemViewHolder as TvGameViewHolder + + // Start the emulation activity and send the path of the clicked ISO to it. + val paths = GameFileCacheManager.findSecondDiscAndGetPaths(holder.gameFile) + EmulationActivity.launch(this@TvMainActivity, paths, false) + } + } + } + + /** + * MainView + */ + override fun setVersionString(version: String) { + browseFragment?.title = version + } + + override fun launchSettingsActivity(menuTag: MenuTag?) { + SettingsActivity.launch(this, menuTag) + } + + override fun launchFileListActivity() { + if (DirectoryInitialization.preferOldFolderPicker(this)) { + FileBrowserHelper.openDirectoryPicker(this, FileBrowserHelper.GAME_EXTENSIONS) + } else { + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) + startActivityForResult(intent, MainPresenter.REQUEST_DIRECTORY) + } + } + + override fun launchOpenFileActivity(requestCode: Int) { + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT) + intent.addCategory(Intent.CATEGORY_OPENABLE) + intent.type = "*/*" + startActivityForResult(intent, requestCode) + } + + /** + * Shows or hides the loading indicator. + */ + override fun setRefreshing(refreshing: Boolean) { + swipeRefresh?.isRefreshing = refreshing + } + + override fun showGames() { + // Kicks off the program services to update all channels + TvUtil.updateAllChannels(applicationContext) + + buildRowsAdapter() + } + + override fun reloadGrid() { + for (row in gameRows) { + row.notifyArrayItemRangeChanged(0, row.size()) + } + } + + override fun showGridOptions() { + GridOptionDialogFragment().show(supportFragmentManager, "gridOptions") + } + + /** + * 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 fun onActivityResult(requestCode: Int, resultCode: Int, result: Intent?) { + super.onActivityResult(requestCode, resultCode, result) + + // If the user picked a file, as opposed to just backing out. + if (resultCode == RESULT_OK) { + val uri = result!!.data + when (requestCode) { + MainPresenter.REQUEST_DIRECTORY -> { + if (DirectoryInitialization.preferOldFolderPicker(this)) { + presenter.onDirectorySelected(FileBrowserHelper.getSelectedPath(result)) + } else { + presenter.onDirectorySelected(result) + } + } + + MainPresenter.REQUEST_GAME_FILE -> FileBrowserHelper.runAfterExtensionCheck( + this, uri, FileBrowserHelper.GAME_LIKE_EXTENSIONS + ) { EmulationActivity.launch(this, result.data.toString(), false) } + + MainPresenter.REQUEST_WAD_FILE -> FileBrowserHelper.runAfterExtensionCheck( + this, uri, FileBrowserHelper.WAD_EXTENSION + ) { presenter.installWAD(result.data.toString()) } + + MainPresenter.REQUEST_WII_SAVE_FILE -> FileBrowserHelper.runAfterExtensionCheck( + this, uri, FileBrowserHelper.BIN_EXTENSION + ) { presenter.importWiiSave(result.data.toString()) } + + MainPresenter.REQUEST_NAND_BIN_FILE -> FileBrowserHelper.runAfterExtensionCheck( + this, uri, FileBrowserHelper.BIN_EXTENSION + ) { presenter.importNANDBin(result.data.toString()) } + } + } else { + MainPresenter.skipRescanningLibrary() + } + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + if (requestCode == PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION) { + if (grantResults[0] == PackageManager.PERMISSION_DENIED) { + PermissionsHandler.setWritePermissionDenied() + } + + DirectoryInitialization.start(this) + GameFileCacheManager.startLoad() + } + } + + /** + * Called when the user requests a refresh by swiping down. + */ + override fun onRefresh() { + setRefreshing(true) + GameFileCacheManager.startRescan() + } + + private fun buildRowsAdapter() { + val rowsAdapter = ArrayObjectAdapter(ListRowPresenter()) + gameRows.clear() + + if (!DirectoryInitialization.isWaitingForWriteAccess(this)) { + GameFileCacheManager.startLoad() + } + + for (platform in Platform.values()) { + val row = + buildGamesRow(platform, GameFileCacheManager.getGameFilesForPlatform(platform)) + + // Add row to the adapter only if it is not empty. + if (row != null) { + rowsAdapter.add(row) + } + } + + rowsAdapter.add(buildSettingsRow()) + + browseFragment!!.adapter = rowsAdapter + } + + private fun buildGamesRow(platform: Platform, gameFiles: Collection): ListRow? { + // If there are no games, don't return a Row. + if (gameFiles.isEmpty()) { + return null + } + + // Create an adapter for this row. + val row = ArrayObjectAdapter(GameRowPresenter(this)) + row.addAll(0, gameFiles) + + // Keep a reference to the row in case we need to refresh it. + gameRows.add(row) + + // Create a header for this row. + val header = HeaderItem(platform.toInt().toLong(), getString(platform.headerName)) + + // Create the row, passing it the filled adapter and the header, and give it to the master adapter. + return ListRow(header, row) + } + + private fun buildSettingsRow(): ListRow { + val rowItems = ArrayObjectAdapter(SettingsRowPresenter()) + rowItems.apply { + add( + TvSettingsItem( + R.id.menu_settings, + R.drawable.ic_settings_tv, + R.string.grid_menu_settings + ) + ) + add( + TvSettingsItem( + R.id.button_add_directory, + R.drawable.ic_add_tv, + R.string.add_directory_title + ) + ) + add( + TvSettingsItem( + R.id.menu_grid_options, + R.drawable.ic_list_tv, + R.string.grid_menu_grid_options + ) + ) + add( + TvSettingsItem( + R.id.menu_refresh, + R.drawable.ic_refresh_tv, + R.string.grid_menu_refresh + ) + ) + add( + TvSettingsItem( + R.id.menu_open_file, + R.drawable.ic_play_tv, + R.string.grid_menu_open_file + ) + ) + add( + TvSettingsItem( + R.id.menu_install_wad, + R.drawable.ic_folder_tv, + R.string.grid_menu_install_wad + ) + ) + add( + TvSettingsItem( + R.id.menu_load_wii_system_menu, + R.drawable.ic_folder_tv, + R.string.grid_menu_load_wii_system_menu + ) + ) + add( + TvSettingsItem( + R.id.menu_import_wii_save, + R.drawable.ic_folder_tv, + R.string.grid_menu_import_wii_save + ) + ) + add( + TvSettingsItem( + R.id.menu_import_nand_backup, + R.drawable.ic_folder_tv, + R.string.grid_menu_import_nand_backup + ) + ) + add( + TvSettingsItem( + R.id.menu_online_system_update, + R.drawable.ic_folder_tv, + R.string.grid_menu_online_system_update + ) + ) + add( + TvSettingsItem( + R.id.menu_about, + R.drawable.ic_info_tv, + R.string.grid_menu_about + ) + ) + } + + // Create a header for this row. + val header = HeaderItem(R.string.settings.toLong(), getString(R.string.settings)) + return ListRow(header, rowItems) + } +} \ No newline at end of file