diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/BaseActivity.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/BaseActivity.java index 72926b076..2462b5958 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/BaseActivity.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/BaseActivity.java @@ -1,5 +1,44 @@ package com.panda3ds.pandroid.app; +import android.os.Bundle; + +import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; -public class BaseActivity extends AppCompatActivity {} +import com.panda3ds.pandroid.R; +import com.panda3ds.pandroid.data.config.GlobalConfig; + +public class BaseActivity extends AppCompatActivity { + private int currentTheme = GlobalConfig.get(GlobalConfig.KEY_APP_THEME); + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + applyTheme(); + super.onCreate(savedInstanceState); + } + + @Override + protected void onResume() { + super.onResume(); + if (GlobalConfig.get(GlobalConfig.KEY_APP_THEME) != currentTheme){ + recreate(); + } + } + + private void applyTheme(){ + switch (GlobalConfig.get(GlobalConfig.KEY_APP_THEME)){ + case GlobalConfig.VALUE_THEME_ANDROID: + setTheme(R.style.Theme_Pandroid); + break; + case GlobalConfig.VALUE_THEME_LIGHT: + setTheme(R.style.Theme_Pandroid_Light); + break; + case GlobalConfig.VALUE_THEME_DARK: + setTheme(R.style.Theme_Pandroid_Dark); + break; + case GlobalConfig.VALUE_THEME_BLACK: + setTheme(R.style.Theme_Pandroid_Black); + break; + } + currentTheme = GlobalConfig.get(GlobalConfig.KEY_APP_THEME); + } +} diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/main/SettingsFragment.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/main/SettingsFragment.java index 22f888fea..08f2d70f8 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/main/SettingsFragment.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/main/SettingsFragment.java @@ -8,11 +8,13 @@ import com.panda3ds.pandroid.app.PreferenceActivity; import com.panda3ds.pandroid.app.base.BasePreferenceFragment; import com.panda3ds.pandroid.app.preferences.InputMapPreferences; +import com.panda3ds.pandroid.app.preferences.AppearancePreferences; public class SettingsFragment extends BasePreferenceFragment { @Override public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) { setPreferencesFromResource(R.xml.start_preferences, rootKey); setItemClick("inputMap", (item) -> PreferenceActivity.launch(requireContext(), InputMapPreferences.class)); + setItemClick("appearance", (item)-> PreferenceActivity.launch(requireContext(), AppearancePreferences.class)); } } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/preferences/AppearancePreferences.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/preferences/AppearancePreferences.java new file mode 100644 index 000000000..63f79ddb4 --- /dev/null +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/preferences/AppearancePreferences.java @@ -0,0 +1,28 @@ +package com.panda3ds.pandroid.app.preferences; + +import android.app.Activity; +import android.os.Bundle; + +import androidx.annotation.Nullable; + +import com.panda3ds.pandroid.R; +import com.panda3ds.pandroid.app.BaseActivity; +import com.panda3ds.pandroid.app.base.BasePreferenceFragment; +import com.panda3ds.pandroid.data.config.GlobalConfig; +import com.panda3ds.pandroid.view.preferences.SingleSelectionPreferences; + +public class AppearancePreferences extends BasePreferenceFragment { + @Override + public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) { + setPreferencesFromResource(R.xml.appearance_preference, rootKey); + + ((BaseActivity) requireActivity()).getSupportActionBar().setTitle(R.string.appearance); + + SingleSelectionPreferences themePreference = findPreference("theme"); + themePreference.setSelectedItem(GlobalConfig.get(GlobalConfig.KEY_APP_THEME)); + themePreference.setOnPreferenceChangeListener((preference, value) -> { + GlobalConfig.set(GlobalConfig.KEY_APP_THEME, (int) value); + return false; + }); + } +} diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/preferences/InputMapPreferences.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/preferences/InputMapPreferences.java index 007920bd9..00f031ac9 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/preferences/InputMapPreferences.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/preferences/InputMapPreferences.java @@ -8,8 +8,10 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.preference.Preference; +import androidx.preference.SeekBarPreference; import com.panda3ds.pandroid.R; +import com.panda3ds.pandroid.app.BaseActivity; import com.panda3ds.pandroid.app.base.BasePreferenceFragment; import com.panda3ds.pandroid.input.InputMap; import com.panda3ds.pandroid.input.KeyName; @@ -19,16 +21,35 @@ public class InputMapPreferences extends BasePreferenceFragment implements Activ private ActivityResultLauncher requestKey; private String currentKey; + private SeekBarPreference deadZonePreference; + @Override public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) { setPreferencesFromResource(R.xml.input_map_preferences, rootKey); + + ((BaseActivity) requireActivity()).getSupportActionBar().setTitle(R.string.controller_mapping); + for (KeyName key : KeyName.values()) { - if (key == KeyName.NULL) return; + if (key == KeyName.NULL) continue; setItemClick(key.name(), this::onItemPressed); } + + deadZonePreference = getPreferenceScreen().findPreference("dead_zone"); + + deadZonePreference.setOnPreferenceChangeListener((preference, value) -> { + InputMap.setDeadZone(((int)value/100.0f)); + refreshList(); + return false; + }); + refreshList(); } + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + @Override public void onAttach(@NonNull Context context) { super.onAttach(context); @@ -56,6 +77,8 @@ public void onResume() { } private void refreshList() { + deadZonePreference.setValue((int)(InputMap.getDeadZone()*100)); + deadZonePreference.setSummary(deadZonePreference.getValue()+"%"); for (KeyName key : KeyName.values()) { if (key == KeyName.NULL) continue; findPreference(key.name()).setSummary(InputMap.relative(key)); diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/config/GlobalConfig.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/config/GlobalConfig.java index d25e34c74..127f2ffa6 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/config/GlobalConfig.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/config/GlobalConfig.java @@ -11,6 +11,13 @@ public class GlobalConfig { private static SharedPreferences data; + public static final int VALUE_THEME_ANDROID = 0; + public static final int VALUE_THEME_LIGHT = 1; + public static final int VALUE_THEME_DARK = 2; + public static final int VALUE_THEME_BLACK = 3; + + public static final Key KEY_APP_THEME = new Key<>("app.theme", VALUE_THEME_ANDROID); + public static void initialize() { data = PandroidApplication.getAppContext() .getSharedPreferences(Constants.PREF_GLOBAL_CONFIG, Context.MODE_PRIVATE); diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/game/GameMetadata.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/game/GameMetadata.java index 464073026..325ce1e71 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/game/GameMetadata.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/game/GameMetadata.java @@ -1,5 +1,7 @@ package com.panda3ds.pandroid.data.game; +import android.graphics.Bitmap; + import java.util.UUID; public class GameMetadata { @@ -7,7 +9,7 @@ public class GameMetadata { private final String id; private final String romPath; private final String title; - private final int[] icon = new int[48 * 48]; + private transient final Bitmap icon = Bitmap.createBitmap(48,48, Bitmap.Config.RGB_565); private final String publisher; private final GameRegion[] regions = new GameRegion[]{GameRegion.None}; @@ -34,7 +36,7 @@ public String getPublisher() { return publisher; } - public int[] getIcon() { + public Bitmap getIcon() { return icon; } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/input/InputMap.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/input/InputMap.java index 6e61345cb..b94ceaace 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/input/InputMap.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/input/InputMap.java @@ -36,7 +36,7 @@ public static KeyName relative(String name) { } public static void setDeadZone(float value) { - data.edit().putFloat(KEY_DEAD_ZONE, Math.max(0, Math.min(1.0F, value))).apply(); + data.edit().putFloat(KEY_DEAD_ZONE, Math.max(0.0f, Math.min(1.0f, value))).apply(); } } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/FileUtils.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/FileUtils.java index 4ebd7241f..a22c4842f 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/FileUtils.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/FileUtils.java @@ -3,8 +3,6 @@ import android.content.Context; import android.content.Intent; import android.net.Uri; -import android.os.ParcelFileDescriptor; -import android.util.Log; import androidx.documentfile.provider.DocumentFile; @@ -27,15 +25,6 @@ public static String getName(String path) { return file.getName(); } - public static long getSize(String path) { - return DocumentFile.fromSingleUri(getContext(), parseUri(path)).length(); - } - - - public static String getCacheDir() { - return getContext().getCacheDir().getAbsolutePath(); - } - public static void makeUriPermanent(String uri, String mode) { int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION; @@ -44,20 +33,4 @@ public static void makeUriPermanent(String uri, String mode) { getContext().getContentResolver().takePersistableUriPermission(parseUri(uri), flags); } - - public static int openContentUri(String path, String mode) { - try { - Uri uri = parseUri(path); - ParcelFileDescriptor descriptor = getContext().getContentResolver().openFileDescriptor(uri, mode); - int fd = descriptor.getFd(); - descriptor.detachFd(); - descriptor.close(); - return fd; - } catch (Exception e) { - Log.e(Constants.LOG_TAG, "Error on openContentUri: " + e); - } - - return -1; - } - } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/ItemHolder.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/ItemHolder.java index d2ccba1fe..54f86daea 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/ItemHolder.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/gamesgrid/ItemHolder.java @@ -18,6 +18,8 @@ public ItemHolder(@NonNull View itemView) { public void apply(GameMetadata game) { ((AppCompatTextView) itemView.findViewById(R.id.title)) .setText(game.getTitle()); + ((GameIconView) itemView.findViewById(R.id.icon)) + .setImageBitmap(game.getIcon()); ((AppCompatTextView) itemView.findViewById(R.id.description)) .setText(game.getPublisher()); diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/preferences/SingleSelectionPreferences.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/preferences/SingleSelectionPreferences.java new file mode 100644 index 000000000..f4ddfd12b --- /dev/null +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/view/preferences/SingleSelectionPreferences.java @@ -0,0 +1,84 @@ +package com.panda3ds.pandroid.view.preferences; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.util.AttributeSet; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.preference.Preference; +import androidx.preference.PreferenceCategory; + +import com.panda3ds.pandroid.R; +import com.panda3ds.pandroid.utils.Constants; + +public class SingleSelectionPreferences extends PreferenceCategory implements Preference.OnPreferenceClickListener { + private final Drawable transparent = new ColorDrawable(Color.TRANSPARENT); + private final Drawable doneDrawable = ContextCompat.getDrawable(getContext(), R.drawable.ic_done); + + public SingleSelectionPreferences(@NonNull Context context) { + super(context); + } + + public SingleSelectionPreferences(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public SingleSelectionPreferences(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public SingleSelectionPreferences(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + { + try { + TypedArray color = getContext().obtainStyledAttributes(new int[]{ + android.R.attr.textColorSecondary + }); + doneDrawable.setTint(color.getColor(0, Color.RED)); + color.recycle(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + color.close(); + } + } catch (Exception e) { + Log.e(Constants.LOG_TAG, "Error on obtain text color secondary: ", e); + } + } + + @Override + public void onAttached() { + super.onAttached(); + for (int i = 0; i < getPreferenceCount();i++) { + getPreference(i).setOnPreferenceClickListener(this); + } + } + + public void setSelectedItem(int index){ + onPreferenceClick(getPreference(index)); + } + + @Override + public boolean onPreferenceClick(@NonNull Preference preference) { + int index = 0; + for (int i = 0; i < getPreferenceCount(); i++){ + Preference item = getPreference(i); + if (item == preference){ + index = i; + item.setIcon(R.drawable.ic_done); + } else { + item.setIcon(transparent); + } + } + + callChangeListener(index); + return false; + } +} diff --git a/src/pandroid/app/src/main/res/color/bottom_navigation_indicator_tint.xml b/src/pandroid/app/src/main/res/color/bottom_navigation_indicator_tint.xml new file mode 100644 index 000000000..e0fc91122 --- /dev/null +++ b/src/pandroid/app/src/main/res/color/bottom_navigation_indicator_tint.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/pandroid/app/src/main/res/color/text_secondary_dark.xml b/src/pandroid/app/src/main/res/color/text_secondary_dark.xml new file mode 100644 index 000000000..53a9cd158 --- /dev/null +++ b/src/pandroid/app/src/main/res/color/text_secondary_dark.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/pandroid/app/src/main/res/color/text_secondary_light.xml b/src/pandroid/app/src/main/res/color/text_secondary_light.xml new file mode 100644 index 000000000..351360585 --- /dev/null +++ b/src/pandroid/app/src/main/res/color/text_secondary_light.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/pandroid/app/src/main/res/drawable/ic_done.xml b/src/pandroid/app/src/main/res/drawable/ic_done.xml new file mode 100644 index 000000000..25e52514c --- /dev/null +++ b/src/pandroid/app/src/main/res/drawable/ic_done.xml @@ -0,0 +1,5 @@ + + + diff --git a/src/pandroid/app/src/main/res/drawable/ic_theme.xml b/src/pandroid/app/src/main/res/drawable/ic_theme.xml new file mode 100644 index 000000000..c3d2c7b31 --- /dev/null +++ b/src/pandroid/app/src/main/res/drawable/ic_theme.xml @@ -0,0 +1,5 @@ + + + diff --git a/src/pandroid/app/src/main/res/drawable/temp_thumb.jpg b/src/pandroid/app/src/main/res/drawable/temp_thumb.jpg deleted file mode 100644 index e66782be3..000000000 Binary files a/src/pandroid/app/src/main/res/drawable/temp_thumb.jpg and /dev/null differ diff --git a/src/pandroid/app/src/main/res/layout-land/activity_main.xml b/src/pandroid/app/src/main/res/layout-land/activity_main.xml index ba552154a..fa4cfbca4 100644 --- a/src/pandroid/app/src/main/res/layout-land/activity_main.xml +++ b/src/pandroid/app/src/main/res/layout-land/activity_main.xml @@ -24,6 +24,7 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:menu="@menu/main_activity_navigation" - app:labelVisibilityMode="selected"/> + app:labelVisibilityMode="selected" + style="@style/ThemedNavigationBottom"/> \ No newline at end of file diff --git a/src/pandroid/app/src/main/res/layout/activity_main.xml b/src/pandroid/app/src/main/res/layout/activity_main.xml index 1facabd35..6de640209 100644 --- a/src/pandroid/app/src/main/res/layout/activity_main.xml +++ b/src/pandroid/app/src/main/res/layout/activity_main.xml @@ -23,6 +23,7 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toBottomOf="@id/fragment_container" app:labelVisibilityMode="selected" - app:menu="@menu/main_activity_navigation"/> + app:menu="@menu/main_activity_navigation" + style="@style/ThemedNavigationBottom"/> \ No newline at end of file diff --git a/src/pandroid/app/src/main/res/layout/holder_game.xml b/src/pandroid/app/src/main/res/layout/holder_game.xml index 169896e6a..b2d46d1b4 100644 --- a/src/pandroid/app/src/main/res/layout/holder_game.xml +++ b/src/pandroid/app/src/main/res/layout/holder_game.xml @@ -13,11 +13,11 @@ app:cardCornerRadius="16dp"> + android:background="?colorSurfaceVariant"/> diff --git a/src/pandroid/app/src/main/res/layout/preference_start_item.xml b/src/pandroid/app/src/main/res/layout/preference_start_item.xml index 35aa55548..ecb10436a 100644 --- a/src/pandroid/app/src/main/res/layout/preference_start_item.xml +++ b/src/pandroid/app/src/main/res/layout/preference_start_item.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="70dp" - android:layout_marginVertical="10dp" + android:layout_marginVertical="4dp" android:layout_marginHorizontal="10dp" android:background="@drawable/simple_card_background" android:backgroundTint="?colorSurfaceVariant"> diff --git a/src/pandroid/app/src/main/res/values-pt-rBR/strings.xml b/src/pandroid/app/src/main/res/values-pt-rBR/strings.xml index 90e533a74..e57feab59 100644 --- a/src/pandroid/app/src/main/res/values-pt-rBR/strings.xml +++ b/src/pandroid/app/src/main/res/values-pt-rBR/strings.xml @@ -13,4 +13,15 @@ Outros Pressione qualquer tecla Eixos + Zona Morta + Opções + Mapeie um controle ou teclado + Mapeamento de controle + Tema + Defina a aparência do aplicativo + Aparência + Mesmo do dispositivo + Claro + Escuro + Preto \ No newline at end of file diff --git a/src/pandroid/app/src/main/res/values/strings.xml b/src/pandroid/app/src/main/res/values/strings.xml index b7855ecac..973e7acb4 100644 --- a/src/pandroid/app/src/main/res/values/strings.xml +++ b/src/pandroid/app/src/main/res/values/strings.xml @@ -14,4 +14,15 @@ Others Press any key Axis + Dead zone + Options + Map physics controller or keyboard + Controller Mapping + Theme + Set application theme + Appearance + Device + Light + Dark + Black \ No newline at end of file diff --git a/src/pandroid/app/src/main/res/values/styleable.xml b/src/pandroid/app/src/main/res/values/styleable.xml index 32e51685b..c4bce805a 100644 --- a/src/pandroid/app/src/main/res/values/styleable.xml +++ b/src/pandroid/app/src/main/res/values/styleable.xml @@ -1,5 +1,8 @@ + + - + + + + \ No newline at end of file diff --git a/src/pandroid/app/src/main/res/values/themes.xml b/src/pandroid/app/src/main/res/values/themes.xml index 812da8ea5..c7d790808 100644 --- a/src/pandroid/app/src/main/res/values/themes.xml +++ b/src/pandroid/app/src/main/res/values/themes.xml @@ -1,9 +1,76 @@ - + + + + + + + + \ No newline at end of file diff --git a/src/pandroid/app/src/main/res/xml/appearance_preference.xml b/src/pandroid/app/src/main/res/xml/appearance_preference.xml new file mode 100644 index 000000000..dd1ed4831 --- /dev/null +++ b/src/pandroid/app/src/main/res/xml/appearance_preference.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/pandroid/app/src/main/res/xml/input_map_preferences.xml b/src/pandroid/app/src/main/res/xml/input_map_preferences.xml index 25b224d13..fbb6221fa 100644 --- a/src/pandroid/app/src/main/res/xml/input_map_preferences.xml +++ b/src/pandroid/app/src/main/res/xml/input_map_preferences.xml @@ -2,6 +2,19 @@ + + + + + + diff --git a/src/pandroid/app/src/main/res/xml/start_preferences.xml b/src/pandroid/app/src/main/res/xml/start_preferences.xml index 48c8d7a93..57a6d32c0 100644 --- a/src/pandroid/app/src/main/res/xml/start_preferences.xml +++ b/src/pandroid/app/src/main/res/xml/start_preferences.xml @@ -1,17 +1,26 @@ - + + app:title="@string/app_name" + app:enabled="false" + app:summary="1.0" + app:layout="@layout/preference_simple_about"/> + app:key="inputMap" + app:icon="@drawable/ic_key_a" + app:title="@string/controller_mapping" + app:summary="@string/pref_input_map_summary" + app:layout="@layout/preference_start_item"/> + + \ No newline at end of file