Android cleanup and bugfixing

This commit is contained in:
wheremyfoodat 2024-02-29 22:52:44 +02:00
parent 02496b57eb
commit 914193a765
34 changed files with 153 additions and 332 deletions

View file

@ -30,7 +30,8 @@ public class BaseActivity extends AppCompatActivity {
private void applyTheme() { private void applyTheme() {
currentTheme = PandroidApplication.getThemeId(); currentTheme = PandroidApplication.getThemeId();
setTheme(currentTheme); setTheme(currentTheme);
if (GlobalConfig.get(GlobalConfig.KEY_APP_THEME) == GlobalConfig.THEME_ANDROID){
if (GlobalConfig.get(GlobalConfig.KEY_APP_THEME) == GlobalConfig.THEME_ANDROID) {
DynamicColors.applyToActivityIfAvailable(this); DynamicColors.applyToActivityIfAvailable(this);
} }
} }

View file

@ -76,7 +76,7 @@ public class GameActivity extends BaseActivity implements EmulatorCallback {
swapScreens(GlobalConfig.get(GlobalConfig.KEY_CURRENT_DS_LAYOUT)); swapScreens(GlobalConfig.get(GlobalConfig.KEY_CURRENT_DS_LAYOUT));
} }
private void changeOverlayVisibility(boolean visible){ private void changeOverlayVisibility(boolean visible) {
findViewById(R.id.overlay_controller).setVisibility(visible ? View.VISIBLE : View.GONE); findViewById(R.id.overlay_controller).setVisibility(visible ? View.VISIBLE : View.GONE);
findViewById(R.id.overlay_controller).invalidate(); findViewById(R.id.overlay_controller).invalidate();
findViewById(R.id.overlay_controller).requestLayout(); findViewById(R.id.overlay_controller).requestLayout();
@ -95,13 +95,14 @@ public class GameActivity extends BaseActivity implements EmulatorCallback {
} }
} }
private void goToPictureInPicture() { private void enablePIP() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder(); PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
builder.setAutoEnterEnabled(true); builder.setAutoEnterEnabled(true);
builder.setSeamlessResizeEnabled(true); builder.setSeamlessResizeEnabled(true);
} }
builder.setAspectRatio(new Rational(10, 14)); builder.setAspectRatio(new Rational(10, 14));
enterPictureInPictureMode(builder.build()); enterPictureInPictureMode(builder.build());
} }
@ -114,7 +115,7 @@ public class GameActivity extends BaseActivity implements EmulatorCallback {
InputHandler.reset(); InputHandler.reset();
if (GlobalConfig.get(GlobalConfig.KEY_PICTURE_IN_PICTURE)) { if (GlobalConfig.get(GlobalConfig.KEY_PICTURE_IN_PICTURE)) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
goToPictureInPicture(); enablePIP();
} }
} else { } else {
drawerFragment.open(); drawerFragment.open();
@ -142,7 +143,7 @@ public class GameActivity extends BaseActivity implements EmulatorCallback {
@Override @Override
public void swapScreens(int index) { public void swapScreens(int index) {
currentDsLayout = index; currentDsLayout = index;
GlobalConfig.set(GlobalConfig.KEY_CURRENT_DS_LAYOUT,index); GlobalConfig.set(GlobalConfig.KEY_CURRENT_DS_LAYOUT, index);
renderer.setLayout(DsLayoutManager.createLayout(currentDsLayout)); renderer.setLayout(DsLayoutManager.createLayout(currentDsLayout));
} }
@ -158,11 +159,13 @@ public class GameActivity extends BaseActivity implements EmulatorCallback {
@Override @Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) { public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode); super.onPictureInPictureModeChanged(isInPictureInPictureMode);
changeOverlayVisibility(!isInPictureInPictureMode && GlobalConfig.get(GlobalConfig.KEY_SCREEN_GAMEPAD_VISIBLE)); changeOverlayVisibility(!isInPictureInPictureMode && GlobalConfig.get(GlobalConfig.KEY_SCREEN_GAMEPAD_VISIBLE));
findViewById(R.id.hide_screen_controller).setVisibility(isInPictureInPictureMode ? View.INVISIBLE : View.VISIBLE); findViewById(R.id.hide_screen_controller).setVisibility(isInPictureInPictureMode ? View.INVISIBLE : View.VISIBLE);
if (isInPictureInPictureMode){
if (isInPictureInPictureMode) {
getWindow().getDecorView().postDelayed(drawerFragment::close, 250); getWindow().getDecorView().postDelayed(drawerFragment::close, 250);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S){ } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
ActivityManager manager = ((ActivityManager) getSystemService(ACTIVITY_SERVICE)); ActivityManager manager = ((ActivityManager) getSystemService(ACTIVITY_SERVICE));
manager.getAppTasks().forEach(ActivityManager.AppTask::moveToFront); manager.getAppTasks().forEach(ActivityManager.AppTask::moveToFront);
} }
@ -173,6 +176,7 @@ public class GameActivity extends BaseActivity implements EmulatorCallback {
if (AlberDriver.HasRomLoaded()) { if (AlberDriver.HasRomLoaded()) {
AlberDriver.Finalize(); AlberDriver.Finalize();
} }
super.onDestroy(); super.onDestroy();
} }
} }

View file

@ -31,12 +31,12 @@ public class MainActivity extends BaseActivity implements NavigationBarView.OnIt
@Override @Override
public void onBackPressed() { public void onBackPressed() {
if (navigationBar.getSelectedItemId() != R.id.games){ if (navigationBar.getSelectedItemId() != R.id.games) {
navigationBar.setSelectedItemId(R.id.games); navigationBar.setSelectedItemId(R.id.games);
return; } else {
}
super.onBackPressed(); super.onBackPressed();
} }
}
@Override @Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) { public boolean onNavigationItemSelected(@NonNull MenuItem item) {

View file

@ -22,7 +22,7 @@ public abstract class BasePreferenceFragment extends PreferenceFragmentCompat {
}); });
} }
protected void setSwitchValue(String id, boolean value){ protected void setSwitchValue(String id, boolean value) {
((SwitchPreferenceCompat)findPreference(id)).setChecked(value); ((SwitchPreferenceCompat)findPreference(id)).setChecked(value);
} }

View file

@ -18,11 +18,15 @@ public class BaseSheetDialog extends BottomSheetDialog {
private final LinearLayout contentView; private final LinearLayout contentView;
public BaseSheetDialog(@NonNull Context context) { public BaseSheetDialog(@NonNull Context context) {
super(CompatUtils.findActivity(context)); super(CompatUtils.findActivity(context));
int width = CompatUtils.findActivity(context).getWindow().getDecorView().getMeasuredWidth(); int width = CompatUtils.findActivity(context).getWindow().getDecorView().getMeasuredWidth();
int height = CompatUtils.findActivity(context).getWindow().getDecorView().getMeasuredHeight(); int height = CompatUtils.findActivity(context).getWindow().getDecorView().getMeasuredHeight();
getBehavior().setPeekHeight((int) (height*0.87)); float heightScale = 0.87f; // What percentage of the screen's height to use up
getBehavior().setPeekHeight((int) (height * heightScale));
getBehavior().setMaxHeight((int) (height * heightScale));
getBehavior().setMaxWidth(width); getBehavior().setMaxWidth(width);
getBehavior().setMaxHeight((int) (height*0.87));
super.setContentView(R.layout.dialog_bottom_sheet); super.setContentView(R.layout.dialog_bottom_sheet);
contentView = super.findViewById(R.id.content); contentView = super.findViewById(R.id.content);
} }

View file

@ -61,14 +61,16 @@ public class GameAboutDialog extends BaseSheetDialog {
} }
} }
// Make a shortcut for a specific game
private void makeShortcut() { private void makeShortcut() {
Context context = CompatUtils.findActivity(getContext()); Context context = CompatUtils.findActivity(getContext());
ShortcutInfoCompat.Builder shortcut = new ShortcutInfoCompat.Builder(context, game.getId()); ShortcutInfoCompat.Builder shortcut = new ShortcutInfoCompat.Builder(context, game.getId());
if (game.getIcon() != null){ if (game.getIcon() != null) {
shortcut.setIcon(IconCompat.createWithAdaptiveBitmap(game.getIcon())); shortcut.setIcon(IconCompat.createWithAdaptiveBitmap(game.getIcon()));
} else { } else {
shortcut.setIcon(IconCompat.createWithResource(getContext(), R.mipmap.ic_launcher)); shortcut.setIcon(IconCompat.createWithResource(getContext(), R.mipmap.ic_launcher));
} }
shortcut.setActivity(new ComponentName(context, GameLauncher.class)); shortcut.setActivity(new ComponentName(context, GameLauncher.class));
shortcut.setLongLabel(game.getTitle()); shortcut.setLongLabel(game.getTitle());
shortcut.setShortLabel(game.getTitle()); shortcut.setShortLabel(game.getTitle());
@ -76,6 +78,6 @@ public class GameAboutDialog extends BaseSheetDialog {
intent.setAction(Intent.ACTION_VIEW); intent.setAction(Intent.ACTION_VIEW);
intent.setData(new Uri.Builder().scheme("pandroid-game").authority(game.getId()).build()); intent.setData(new Uri.Builder().scheme("pandroid-game").authority(game.getId()).build());
shortcut.setIntent(intent); shortcut.setIntent(intent);
ShortcutManagerCompat.requestPinShortcut(context,shortcut.build(),null); ShortcutManagerCompat.requestPinShortcut(context, shortcut.build(), null);
} }
} }

View file

@ -13,7 +13,7 @@ import com.panda3ds.pandroid.R;
public class LoadingAlertDialog extends BottomAlertDialog { public class LoadingAlertDialog extends BottomAlertDialog {
public LoadingAlertDialog(@NonNull Context context, @StringRes int title) { public LoadingAlertDialog(@NonNull Context context, @StringRes int title) {
super(context); super(context);
View view = LayoutInflater.from(context).inflate(R.layout.dialog_loading,null, false); View view = LayoutInflater.from(context).inflate(R.layout.dialog_loading, null, false);
setView(view); setView(view);
setCancelable(false); setCancelable(false);
((AppCompatTextView)view.findViewById(R.id.title)) ((AppCompatTextView)view.findViewById(R.id.title))

View file

@ -49,7 +49,7 @@ public class AlberInputListener implements Function<InputEvent> {
axisChanged = true; axisChanged = true;
break; break;
case CHANGE_DS_LAYOUT: case CHANGE_DS_LAYOUT:
if (!event.isDown()){ if (!event.isDown()) {
emulator.swapScreens(); emulator.swapScreens();
} }
break; break;

View file

@ -52,7 +52,7 @@ public class DrawerFragment extends Fragment implements DrawerLayout.DrawerListe
refresh(); refresh();
} }
private void refresh(){ private void refresh() {
game = GameUtils.getCurrentGame(); game = GameUtils.getCurrentGame();
if (game.getIcon() != null && !game.getIcon().isRecycled()) { if (game.getIcon() != null && !game.getIcon().isRecycled()) {
((GameIconView) drawerLayout.findViewById(R.id.game_icon)).setImageBitmap(game.getIcon()); ((GameIconView) drawerLayout.findViewById(R.id.game_icon)).setImageBitmap(game.getIcon());
@ -61,7 +61,6 @@ public class DrawerFragment extends Fragment implements DrawerLayout.DrawerListe
} }
((AppCompatTextView)drawerLayout.findViewById(R.id.game_title)).setText(game.getTitle()); ((AppCompatTextView)drawerLayout.findViewById(R.id.game_title)).setText(game.getTitle());
((AppCompatTextView)drawerLayout.findViewById(R.id.game_publisher)).setText(game.getPublisher()); ((AppCompatTextView)drawerLayout.findViewById(R.id.game_publisher)).setText(game.getPublisher());
} }
@Override @Override

View file

@ -5,7 +5,8 @@ import com.panda3ds.pandroid.data.config.GlobalConfig;
public interface EmulatorCallback { public interface EmulatorCallback {
void onBackPressed(); void onBackPressed();
void swapScreens(int index); void swapScreens(int index);
default void swapScreens() { default void swapScreens() {
swapScreens(GlobalConfig.get(GlobalConfig.KEY_CURRENT_DS_LAYOUT)+1); swapScreens(GlobalConfig.get(GlobalConfig.KEY_CURRENT_DS_LAYOUT) + 1);
} }
} }

View file

@ -21,17 +21,19 @@ public class GameLauncher extends BaseActivity {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(new TextView(this)); setContentView(new TextView(this));
Uri uri = getIntent().getData(); Uri uri = getIntent().getData();
if(uri != null && uri.getScheme().equals("pandroid-game")){ if (uri != null && uri.getScheme().equals("pandroid-game")) {
String gameId = uri.getAuthority(); String gameId = uri.getAuthority();
GameMetadata game = GameUtils.findGameById(gameId); GameMetadata game = GameUtils.findGameById(gameId);
if (game != null){
if (game != null) {
GameUtils.launch(this, game); GameUtils.launch(this, game);
} else { } else {
Toast.makeText(this, R.string.invalid_game,Toast.LENGTH_LONG).show(); Toast.makeText(this, R.string.invalid_game, Toast.LENGTH_LONG).show();
ShortcutManagerCompat.removeDynamicShortcuts(this, Arrays.asList(gameId)); ShortcutManagerCompat.removeDynamicShortcuts(this, Arrays.asList(gameId));
ShortcutManagerCompat.removeLongLivedShortcuts(this, Arrays.asList(gameId)); ShortcutManagerCompat.removeLongLivedShortcuts(this, Arrays.asList(gameId));
} }
} }
finish(); finish();
} }
} }

View file

@ -27,8 +27,8 @@ public class SettingsFragment extends BasePreferenceFragment {
try { try {
Context context = PandroidApplication.getAppContext(); Context context = PandroidApplication.getAppContext();
return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName; return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
} catch (Exception e){ } catch (Exception e) {
return "???"; return "Error: Unknown version";
} }
} }
} }

View file

@ -51,14 +51,14 @@ public class GamesFoldersPreferences extends BasePreferenceFragment implements A
screen.addPreference(preference); screen.addPreference(preference);
} }
Preference add = new Preference(screen.getContext()); Preference pref = new Preference(screen.getContext());
add.setTitle(R.string.import_folder); pref.setTitle(R.string.import_folder);
add.setIcon(R.drawable.ic_add); pref.setIcon(R.drawable.ic_add);
add.setOnPreferenceClickListener(preference -> { pref.setOnPreferenceClickListener(preference -> {
pickFolderRequest.launch(null); pickFolderRequest.launch(null);
return false; return false;
}); });
screen.addPreference(add); screen.addPreference(pref);
} }
private void showFolderInfo(GamesFolder folder) { private void showFolderInfo(GamesFolder folder) {
@ -83,6 +83,7 @@ public class GamesFoldersPreferences extends BasePreferenceFragment implements A
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
if (pickFolderRequest != null) { if (pickFolderRequest != null) {
pickFolderRequest.unregister(); pickFolderRequest.unregister();
pickFolderRequest = null; pickFolderRequest = null;

View file

@ -29,7 +29,7 @@ public class GeneralPreferences extends BasePreferenceFragment {
refresh(); refresh();
} }
private void refresh(){ private void refresh() {
setSwitchValue("behavior.pictureInPicture", GlobalConfig.get(GlobalConfig.KEY_PICTURE_IN_PICTURE)); setSwitchValue("behavior.pictureInPicture", GlobalConfig.get(GlobalConfig.KEY_PICTURE_IN_PICTURE));
} }
} }

View file

@ -80,7 +80,7 @@ public class InputPreferences extends BasePreferenceFragment {
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
private void refreshScreenProfileList() { private void refreshScreenProfileList() {
PreferenceCategory category = findPreference(ID_GAMEPAD_PROFILE_LIST); PreferenceCategory category = findPreference(ID_GAMEPAD_PROFILE_LIST);
Preference add = category.getPreference(category.getPreferenceCount() - 1); Preference pref = category.getPreference(category.getPreferenceCount() - 1);
category.removeAll(); category.removeAll();
category.setOrderingAsAdded(true); category.setOrderingAsAdded(true);
@ -97,8 +97,8 @@ public class InputPreferences extends BasePreferenceFragment {
category.addPreference(item); category.addPreference(item);
} }
add.setOrder(category.getPreferenceCount()); pref.setOrder(category.getPreferenceCount());
category.addPreference(add); category.addPreference(pref);
} }
@Override @Override

View file

@ -20,13 +20,14 @@ public class ScreenLayoutsPreference extends BasePreferenceFragment {
refresh(); refresh();
} }
public void refresh(){ public void refresh() {
PreferenceScreen screen = getPreferenceScreen(); PreferenceScreen screen = getPreferenceScreen();
screen.removeAll(); screen.removeAll();
for (int i = 0; i < DsLayoutManager.getLayoutCount(); i++){
for (int i = 0; i < DsLayoutManager.getLayoutCount(); i++) {
Preference pref = new Preference(getPreferenceScreen().getContext()); Preference pref = new Preference(getPreferenceScreen().getContext());
pref.setIconSpaceReserved(false); pref.setIconSpaceReserved(false);
pref.setTitle("Layout "+(i+1)); pref.setTitle("Layout "+ (i + 1));
pref.setSummary(R.string.click_to_change); pref.setSummary(R.string.click_to_change);
pref.setIcon(R.drawable.ic_edit); pref.setIcon(R.drawable.ic_edit);
pref.setKey(String.valueOf(i)); pref.setKey(String.valueOf(i));

View file

@ -79,6 +79,7 @@ public class AppDataDocumentProvider extends DocumentsProvider {
.add(Root.COLUMN_TITLE, context().getString(R.string.app_name)) .add(Root.COLUMN_TITLE, context().getString(R.string.app_name))
.add(Root.COLUMN_MIME_TYPES, "*/*") .add(Root.COLUMN_MIME_TYPES, "*/*")
.add(Root.COLUMN_ICON, R.mipmap.ic_launcher); .add(Root.COLUMN_ICON, R.mipmap.ic_launcher);
return cursor; return cursor;
} }
@ -87,6 +88,7 @@ public class AppDataDocumentProvider extends DocumentsProvider {
File file = obtainFile(documentId); File file = obtainFile(documentId);
MatrixCursor cursor = new MatrixCursor(projection == null ? DEFAULT_DOCUMENT_PROJECTION : projection); MatrixCursor cursor = new MatrixCursor(projection == null ? DEFAULT_DOCUMENT_PROJECTION : projection);
includeFile(cursor, file); includeFile(cursor, file);
return cursor; return cursor;
} }
@ -125,20 +127,20 @@ public class AppDataDocumentProvider extends DocumentsProvider {
public String createDocument(String parentDocumentId, String mimeType, String displayName) throws FileNotFoundException { public String createDocument(String parentDocumentId, String mimeType, String displayName) throws FileNotFoundException {
File parent = obtainFile(parentDocumentId); File parent = obtainFile(parentDocumentId);
File file = new File(parent, displayName); File file = new File(parent, displayName);
if (!parent.exists()){ if (!parent.exists()) {
throw new FileNotFoundException("Parent don't exists"); throw new FileNotFoundException("Parent doesn't exist");
} }
if (Objects.equals(mimeType, Document.MIME_TYPE_DIR)){ if (Objects.equals(mimeType, Document.MIME_TYPE_DIR)) {
if (!file.mkdirs()){ if (!file.mkdirs()) {
throw new FileNotFoundException("Error on create directory"); throw new FileNotFoundException("Error while creating directory");
} }
} else { } else {
try { try {
if (!file.createNewFile()){ if (!file.createNewFile()) {
throw new Exception("Error on create file"); throw new Exception("Error while creating file");
} }
} catch (Exception e){ } catch (Exception e) {
throw new FileNotFoundException(e.getMessage()); throw new FileNotFoundException(e.getMessage());
} }
} }
@ -148,7 +150,7 @@ public class AppDataDocumentProvider extends DocumentsProvider {
@Override @Override
public void deleteDocument(String documentId) throws FileNotFoundException { public void deleteDocument(String documentId) throws FileNotFoundException {
File file = obtainFile(documentId); File file = obtainFile(documentId);
if (file.exists()){ if (file.exists()) {
FileUtils.delete(file.getAbsolutePath()); FileUtils.delete(file.getAbsolutePath());
} else { } else {
throw new FileNotFoundException("File not exists"); throw new FileNotFoundException("File not exists");

View file

@ -33,7 +33,7 @@ public class GsonConfigParser {
new Task(()->{ new Task(()->{
if (FileUtils.exists(getPath())) { if (FileUtils.exists(getPath())) {
String src = FileUtils.readTextFile(getPath()); String src = FileUtils.readTextFile(getPath());
if(src != null && src.length() > 2){ if (src != null && src.length() > 2) {
content[0] = src; content[0] = src;
} }
} }

View file

@ -60,17 +60,19 @@ public class GlobalConfig {
writeChanges(); writeChanges();
} }
public static <T extends Object> T getExtra(Key<String> key, Class<T> dataClass){ public static <T extends Object> T getExtra(Key<String> key, Class<T> dataClass) {
if (data.extras.has(key.name)){ if (data.extras.has(key.name)) {
return gson.fromJson(data.extras.getAsJsonObject(key.name), dataClass); return gson.fromJson(data.extras.getAsJsonObject(key.name), dataClass);
} }
return gson.fromJson("{}", dataClass); return gson.fromJson("{}", dataClass);
} }
public static synchronized void putExtra(Key<String> key, Object value){ public static synchronized void putExtra(Key<String> key, Object value) {
if (data.extras.has(key.name)){ if (data.extras.has(key.name)) {
data.extras.remove(key.name); data.extras.remove(key.name);
} }
data.extras.add(key.name, gson.toJsonTree(value)); data.extras.add(key.name, gson.toJsonTree(value));
writeChanges(); writeChanges();
} }

View file

@ -83,9 +83,10 @@ public class GameMetadata {
this.title = smdh.getTitle(); this.title = smdh.getTitle();
this.publisher = smdh.getPublisher(); this.publisher = smdh.getPublisher();
this.icon = icon; this.icon = icon;
if (icon != null){ if (icon != null) {
GameUtils.setGameIcon(id, icon); GameUtils.setGameIcon(id, icon);
} }
this.regions = new GameRegion[]{smdh.getRegion()}; this.regions = new GameRegion[]{smdh.getRegion()};
GameUtils.writeChanges(); GameUtils.writeChanges();
} }

View file

@ -12,8 +12,8 @@ public enum GameRegion {
Taiwan, Taiwan,
None; None;
public int localizedName(){ public int localizedName() {
switch (this){ switch (this) {
case NorthAmerican: case NorthAmerican:
return R.string.region_north_armerican; return R.string.region_north_armerican;
case Japan: case Japan:

View file

@ -12,7 +12,6 @@ import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
public class GamesFolder { public class GamesFolder {
private final String id = UUID.randomUUID().toString(); private final String id = UUID.randomUUID().toString();
private final String path; private final String path;
private final HashMap<String, GameMetadata> games = new HashMap<>(); private final HashMap<String, GameMetadata> games = new HashMap<>();
@ -21,7 +20,7 @@ public class GamesFolder {
this.path = path; this.path = path;
} }
public boolean isValid(){ public boolean isValid() {
return FileUtils.exists(path); return FileUtils.exists(path);
} }
@ -39,22 +38,24 @@ public class GamesFolder {
public void refresh() { public void refresh() {
String[] gamesId = games.keySet().toArray(new String[0]); String[] gamesId = games.keySet().toArray(new String[0]);
for (String file: gamesId){ for (String file: gamesId) {
if (!FileUtils.exists(path+"/"+file)){ if (!FileUtils.exists(path + "/" + file)) {
games.remove(file); games.remove(file);
} }
} }
String unknown = PandroidApplication.getAppContext().getString(R.string.unknown); String unknown = PandroidApplication.getAppContext().getString(R.string.unknown);
for (String file: FileUtils.listFiles(path)){ for (String file: FileUtils.listFiles(path)) {
String path = FileUtils.getChild(this.path, file); String path = FileUtils.getChild(this.path, file);
if (FileUtils.isDirectory(path) || games.containsKey(file)){ if (FileUtils.isDirectory(path) || games.containsKey(file)) {
continue; continue;
} }
String ext = FileUtils.extension(path); String ext = FileUtils.extension(path);
if (ext.equals("3ds") || ext.equals("3dsx")){ if (ext.equals("3ds") || ext.equals("3dsx") || ext.equals("cci") || ext.equals("cxi") || ext.equals("app") || ext.equals("ncch")) {
String name = FileUtils.getName(path).trim().split("\\.")[0]; String name = FileUtils.getName(path).trim().split("\\.")[0];
games.put(file, new GameMetadata(new Uri.Builder().path(file).authority(id).scheme("folder").build().toString(),name, unknown)); games.put(file, new GameMetadata(new Uri.Builder().path(file).authority(id).scheme("folder").build().toString(), name, unknown));
} }
} }
} }

View file

@ -110,13 +110,14 @@ public class InputHandler {
} }
} }
String code = KeyEvent.keyCodeToString(event.getKeyCode()); String code = KeyEvent.keyCodeToString(event.getKeyCode());
if (event.getAction() == KeyEvent.ACTION_UP){ if (event.getAction() == KeyEvent.ACTION_UP) {
keyDownEvents.remove(code); keyDownEvents.remove(code);
handleEvent(new InputEvent(code, 0.0f)); handleEvent(new InputEvent(code, 0.0f));
} else if (!keyDownEvents.containsKey(code)){ } else if (!keyDownEvents.containsKey(code)) {
keyDownEvents.put(code, new InputEvent(code, 1.0f)); keyDownEvents.put(code, new InputEvent(code, 1.0f));
} }
for (InputEvent env: keyDownEvents.values()){
for (InputEvent env: keyDownEvents.values()) {
handleEvent(env); handleEvent(env);
} }

View file

@ -19,21 +19,22 @@ public class CompatUtils {
} else if ((context instanceof ContextWrapper)) { } else if ((context instanceof ContextWrapper)) {
return findActivity(((ContextWrapper) context).getBaseContext()); return findActivity(((ContextWrapper) context).getBaseContext());
} }
return ((Activity) context); return ((Activity) context);
} }
public static int resolveColor(Context context, @AttrRes int id){ public static int resolveColor(Context context, @AttrRes int id) {
try { try {
TypedArray values = context.obtainStyledAttributes(new int[]{id}); TypedArray values = context.obtainStyledAttributes(new int[]{id});
int color = values.getColor(0, Color.RED); int color = values.getColor(0, Color.RED);
values.recycle(); values.recycle();
return color; return color;
} catch (Exception e){ } catch (Exception e) {
return Color.rgb(255,0,255); return Color.rgb(255,0,255);
} }
} }
public static float applyDimen(int unit, int size) { public static float applyDimensions(int unit, int size) {
return TypedValue.applyDimension(unit, size, PandroidApplication.getAppContext().getResources().getDisplayMetrics()); return TypedValue.applyDimension(unit, size, PandroidApplication.getAppContext().getResources().getDisplayMetrics());
} }
} }

View file

@ -31,12 +31,13 @@ public class FileUtils {
} }
Uri uri = Uri.parse(path); Uri uri = Uri.parse(path);
DocumentFile singleFile = DocumentFile.fromSingleUri(getContext(), uri); DocumentFile singleFile = DocumentFile.fromSingleUri(getContext(), uri);
if (singleFile.length() > 0 && singleFile.length() != 4096){ if (singleFile.length() > 0 && singleFile.length() != 4096) {
return singleFile; return singleFile;
} }
if (uri.getScheme().equals("content") && uri.getPath().startsWith("/"+TREE_URI)){ if (uri.getScheme().equals("content") && uri.getPath().startsWith("/" + TREE_URI)) {
return DocumentFile.fromTreeUri(getContext(), uri); return DocumentFile.fromTreeUri(getContext(), uri);
} }
return singleFile; return singleFile;
} }
@ -264,22 +265,26 @@ public class FileUtils {
FileUtils.createFile(path, name); FileUtils.createFile(path, name);
InputStream in = getInputStream(source); InputStream in = getInputStream(source);
OutputStream out = getOutputStream(fullPath); OutputStream out = getOutputStream(fullPath);
byte[] buffer = new byte[1024 * 128]; //128 KB // Make a 128KB temp buffer used for copying in chunks
byte[] buffer = new byte[1024 * 128];
int length; int length;
while ((length = in.read(buffer)) != -1) { while ((length = in.read(buffer)) != -1) {
out.write(buffer, 0, length); out.write(buffer, 0, length);
} }
out.flush(); out.flush();
out.close(); out.close();
in.close(); in.close();
} catch (Exception e) { } catch (Exception e) {
Log.e(Constants.LOG_TAG, "ERROR ON COPY FILE", e); Log.e(Constants.LOG_TAG, "Error while trying to copy file", e);
return false; return false;
} }
return true; return true;
} }
public static String getChild(String path, String name){ public static String getChild(String path, String name) {
return parseFile(path).findFile(name).getUri().toString(); return parseFile(path).findFile(name).getUri().toString();
} }

View file

@ -88,7 +88,7 @@ public class GameUtils {
String[] keys = data.folders.keySet().toArray(new String[0]); String[] keys = data.folders.keySet().toArray(new String[0]);
for (String key : keys) { for (String key : keys) {
GamesFolder folder = data.folders.get(key); GamesFolder folder = data.folders.get(key);
if (!folder.isValid()){ if (!folder.isValid()) {
data.folders.remove(key); data.folders.remove(key);
} else { } else {
folder.refresh(); folder.refresh();
@ -100,7 +100,7 @@ public class GameUtils {
public static ArrayList<GameMetadata> getGames() { public static ArrayList<GameMetadata> getGames() {
ArrayList<GameMetadata> games = new ArrayList<>(); ArrayList<GameMetadata> games = new ArrayList<>();
games.addAll(data.games); games.addAll(data.games);
for (GamesFolder folder: data.folders.values()){ for (GamesFolder folder: data.folders.values()) {
games.addAll(folder.getGames()); games.addAll(folder.getGames());
} }
return games; return games;
@ -144,9 +144,9 @@ public class GameUtils {
} }
public static void registerFolder(String path) { public static void registerFolder(String path) {
if (!data.folders.containsKey(path)){ if (!data.folders.containsKey(path)) {
GamesFolder folder = new GamesFolder(path); GamesFolder folder = new GamesFolder(path);
data.folders.put(folder.getId(),folder); data.folders.put(folder.getId(), folder);
folder.refresh(); folder.refresh();
writeChanges(); writeChanges();
} }
@ -158,11 +158,12 @@ public class GameUtils {
} }
public static GameMetadata findGameById(String id) { public static GameMetadata findGameById(String id) {
for (GameMetadata game: getGames()){ for (GameMetadata game: getGames()) {
if (game.getId().equals(id)){ if (game.getId().equals(id)) {
return game; return game;
} }
} }
return null; return null;
} }

View file

@ -8,24 +8,24 @@ class Bounds {
public int top = 0; public int top = 0;
public int bottom = 0; public int bottom = 0;
public void normalize(){ public void normalize() {
left = Math.abs(left); left = Math.abs(left);
right = Math.abs(right); right = Math.abs(right);
top = Math.abs(top); top = Math.abs(top);
bottom = Math.abs(bottom); bottom = Math.abs(bottom);
} }
public void applyWithAspect(Rect rect, int width, double aspectRatio){ public void applyWithAspect(Rect rect, int width, double aspectRatio) {
normalize(); normalize();
rect.set(left, top, width-right, (int) Math.round((width-right-left)*aspectRatio)+top); rect.set(left, top, width-right, (int) Math.round((width-right-left)*aspectRatio)+top);
} }
public void apply(Rect rect, int width, int height){ public void apply(Rect rect, int width, int height) {
normalize(); normalize();
rect.set(left, top, width-right, height-bottom); rect.set(left, top, width-right, height-bottom);
} }
public void move(int x, int y){ public void move(int x, int y) {
left += x; left += x;
right -= x; right -= x;
@ -35,12 +35,14 @@ class Bounds {
} }
public void fixOverlay(int width, int height, int size) { public void fixOverlay(int width, int height, int size) {
if (left > (width-right) - size){ if (left > (width - right) - size) {
right = (width-left) - size; right = (width - left) - size;
} }
if (top > (height - bottom) - size){
if (top > (height - bottom) - size) {
bottom = (height - top) - size; bottom = (height - top) - size;
} }
normalize(); normalize();
} }
} }

View file

@ -51,13 +51,13 @@ public class DsEditorView extends FrameLayout {
public DsEditorView(Context context, int index) { public DsEditorView(Context context, int index) {
super(context); super(context);
layout = (DsLayout) DsLayoutManager.createLayout(index); layout = (DsLayout) DsLayoutManager.createLayout(index);
SIZE_DP = CompatUtils.applyDimen(TypedValue.COMPLEX_UNIT_DIP, 1); SIZE_DP = CompatUtils.applyDimensions(TypedValue.COMPLEX_UNIT_DIP, 1);
int colorBottomSelection = CompatUtils.resolveColor(context, androidx.appcompat.R.attr.colorPrimary); int colorBottomSelection = CompatUtils.resolveColor(context, androidx.appcompat.R.attr.colorPrimary);
int colorTopSelection = CompatUtils.resolveColor(context, com.google.android.material.R.attr.colorAccent); int colorTopSelection = CompatUtils.resolveColor(context, com.google.android.material.R.attr.colorAccent);
selectionPaint.setColor(colorTopSelection); selectionPaint.setColor(colorTopSelection);
selectionPaint.setStrokeWidth(SIZE_DP * 2); selectionPaint.setStrokeWidth(SIZE_DP * 2);
selectionPaint.setPathEffect(new DashPathEffect(new float[]{SIZE_DP * 10, SIZE_DP * 10}, 0.0f)); selectionPaint.setPathEffect(new DashPathEffect(new float[] { SIZE_DP * 10, SIZE_DP * 10 }, 0.0f));
selectionPaint.setStyle(Paint.Style.STROKE); selectionPaint.setStyle(Paint.Style.STROKE);
layout.setTopDisplaySourceSize(Constants.N3DS_WIDTH, Constants.N3DS_HALF_HEIGHT); layout.setTopDisplaySourceSize(Constants.N3DS_WIDTH, Constants.N3DS_HALF_HEIGHT);
@ -71,14 +71,17 @@ public class DsEditorView extends FrameLayout {
layout.getCurrentModel().gravity = Gravity.TOP; layout.getCurrentModel().gravity = Gravity.TOP;
refreshLayout(); refreshLayout();
}); });
gravityAnchor.findViewById(R.id.center).setOnClickListener(v -> { gravityAnchor.findViewById(R.id.center).setOnClickListener(v -> {
layout.getCurrentModel().gravity = Gravity.CENTER; layout.getCurrentModel().gravity = Gravity.CENTER;
refreshLayout(); refreshLayout();
}); });
gravityAnchor.findViewById(R.id.down).setOnClickListener(v -> { gravityAnchor.findViewById(R.id.down).setOnClickListener(v -> {
layout.getCurrentModel().gravity = Gravity.BOTTOM; layout.getCurrentModel().gravity = Gravity.BOTTOM;
refreshLayout(); refreshLayout();
}); });
gravityAnchor.findViewById(R.id.revert).setOnClickListener(v -> { gravityAnchor.findViewById(R.id.revert).setOnClickListener(v -> {
layout.getCurrentModel().reverse = !layout.getCurrentModel().reverse; layout.getCurrentModel().reverse = !layout.getCurrentModel().reverse;
refreshLayout(); refreshLayout();
@ -87,7 +90,7 @@ public class DsEditorView extends FrameLayout {
{ {
modeSelectorLayout = (LinearLayout) inflater.inflate(R.layout.ds_editor_spinner, this, false); modeSelectorLayout = (LinearLayout) inflater.inflate(R.layout.ds_editor_spinner, this, false);
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(getContext(), R.layout.ds_editor_spinner_label); ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(getContext(), R.layout.ds_editor_spinner_label);
spinnerAdapter.addAll("SINGLE", "RELATIVE", "ABSOLUTE"); spinnerAdapter.addAll("Single", "Relative", "Absolute");
modeSelector = modeSelectorLayout.findViewById(R.id.spinner); modeSelector = modeSelectorLayout.findViewById(R.id.spinner);
modeSelector.setAdapter(spinnerAdapter); modeSelector.setAdapter(spinnerAdapter);
modeSelector.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { modeSelector.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@ -149,6 +152,7 @@ public class DsEditorView extends FrameLayout {
@Override @Override
public void draw(Canvas canvas) { public void draw(Canvas canvas) {
super.draw(canvas); super.draw(canvas);
if (this.width != getWidth() || this.height != getHeight()) { if (this.width != getWidth() || this.height != getHeight()) {
this.width = getWidth(); this.width = getWidth();
this.height = getHeight(); this.height = getHeight();
@ -172,12 +176,12 @@ public class DsEditorView extends FrameLayout {
spacePoint.setCenterPosition(primaryDisplay.width(), (int) (SIZE_DP * 15)); spacePoint.setCenterPosition(primaryDisplay.width(), (int) (SIZE_DP * 15));
spacePoint.setText(String.valueOf((int) (data.space * 100))); spacePoint.setText(String.valueOf((int) (data.space * 100)));
} }
}
break; break;
}
case SINGLE: case SINGLE:
case ABSOLUTE: { case ABSOLUTE: break;
}
break;
} }
this.topDisplay.setSize(topDisplay.width(), topDisplay.height()); this.topDisplay.setSize(topDisplay.width(), topDisplay.height());
@ -212,19 +216,23 @@ public class DsEditorView extends FrameLayout {
if (landscape) { if (landscape) {
addView(spacePoint); addView(spacePoint);
} }
}
break; break;
}
case ABSOLUTE: { case ABSOLUTE: {
addView(aspectRatioFixLayout, new LayoutParams(WRAP_CONTENT, WRAP_CONTENT, Gravity.CENTER | Gravity.TOP)); addView(aspectRatioFixLayout, new LayoutParams(WRAP_CONTENT, WRAP_CONTENT, Gravity.CENTER | Gravity.TOP));
addView(topDisplayResizer); addView(topDisplayResizer);
addView(bottomDisplayResizer); addView(bottomDisplayResizer);
}
break; break;
}
case SINGLE: { case SINGLE: {
addView(aspectRatioFixLayout, new LayoutParams(WRAP_CONTENT, WRAP_CONTENT, Gravity.CENTER | Gravity.TOP)); addView(aspectRatioFixLayout, new LayoutParams(WRAP_CONTENT, WRAP_CONTENT, Gravity.CENTER | Gravity.TOP));
}
break; break;
} }
}
((MaterialCheckBox) aspectRatioFixLayout.findViewById(R.id.checkbox)).setChecked(layout.getCurrentModel().lockAspect); ((MaterialCheckBox) aspectRatioFixLayout.findViewById(R.id.checkbox)).setChecked(layout.getCurrentModel().lockAspect);
modeSelector.setSelection(layout.getCurrentModel().mode.ordinal()); modeSelector.setSelection(layout.getCurrentModel().mode.ordinal());
@ -233,7 +241,6 @@ public class DsEditorView extends FrameLayout {
} }
private class PointView extends AppCompatTextView { private class PointView extends AppCompatTextView {
public PointView() { public PointView() {
super(DsEditorView.this.getContext()); super(DsEditorView.this.getContext());
setLayoutParams(new FrameLayout.LayoutParams((int) (SIZE_DP * 30), (int) (SIZE_DP * 30))); setLayoutParams(new FrameLayout.LayoutParams((int) (SIZE_DP * 30), (int) (SIZE_DP * 30)));
@ -302,6 +309,7 @@ public class DsEditorView extends FrameLayout {
downEvent = new Vector2(event.getRawX(), event.getRawY()); downEvent = new Vector2(event.getRawX(), event.getRawY());
return true; return true;
} }
preferred.move((int) (event.getRawX() - downEvent.x), (int) (event.getRawY() - downEvent.y)); preferred.move((int) (event.getRawX() - downEvent.x), (int) (event.getRawY() - downEvent.y));
downEvent.set(event.getRawX(), event.getRawY()); downEvent.set(event.getRawX(), event.getRawY());
refreshPoints(); refreshPoints();
@ -330,6 +338,7 @@ public class DsEditorView extends FrameLayout {
refreshPoints(); refreshPoints();
return true; return true;
} }
return false; return false;
} }
} }

View file

@ -102,12 +102,7 @@ class DsLayout implements ConsoleLayout {
(data.onlyTop ? bottomDisplay : topDisplay).set(0, 0, 0, 0); (data.onlyTop ? bottomDisplay : topDisplay).set(0, 0, 0, 0);
} }
// Relative layout: Organize screen position based on gravity and space, the space determined by the top screen size in landscape mode
/***
* RELATIVE LAYOUT:
* ORGANIZE SCREEN IN POSITION BASED IN GRAVITY
* AND SPACE, THE SPACE DETERMINE LANDSCAPE TOP SCREEN SIZE
*/
private void relative(Model data) { private void relative(Model data) {
int screenWidth = (int) screenSize.x; int screenWidth = (int) screenSize.x;
int screenHeight = (int) screenSize.y; int screenHeight = (int) screenSize.y;
@ -144,14 +139,15 @@ class DsLayout implements ConsoleLayout {
case Gravity.CENTER: { case Gravity.CENTER: {
bottomDisplay.offset(0, (screenHeight - bottomDisplay.height()) / 2); bottomDisplay.offset(0, (screenHeight - bottomDisplay.height()) / 2);
topDisplay.offset(0, (screenHeight - topDisplay.height()) / 2); topDisplay.offset(0, (screenHeight - topDisplay.height()) / 2);
}
break; break;
}
case Gravity.BOTTOM: { case Gravity.BOTTOM: {
bottomDisplay.offset(0, (screenHeight - bottomDisplay.height())); bottomDisplay.offset(0, (screenHeight - bottomDisplay.height()));
topDisplay.offset(0, (screenHeight - topDisplay.height())); topDisplay.offset(0, (screenHeight - topDisplay.height()));
}
break; break;
} }
}
} else { } else {
int topScreenHeight = (int) ((screenWidth / topSourceSize.x) * topSourceSize.y); int topScreenHeight = (int) ((screenWidth / topSourceSize.x) * topSourceSize.y);

View file

@ -10,7 +10,7 @@ public class DsLayoutManager {
static { static {
data = GlobalConfig.getExtra(GlobalConfig.KEY_DS_LAYOUTS, DataModel.class); data = GlobalConfig.getExtra(GlobalConfig.KEY_DS_LAYOUTS, DataModel.class);
if (data.models.size() == 0){ if (data.models.size() == 0) {
setupBasicModels(); setupBasicModels();
} }
} }
@ -26,24 +26,24 @@ public class DsLayoutManager {
model3.mode = Mode.SINGLE; model3.mode = Mode.SINGLE;
model3.onlyTop = true; model3.onlyTop = true;
data.models.add(new Model[]{model1, model1.clone()}); data.models.add(new Model[] {model1, model1.clone()});
data.models.add(new Model[]{model2, model2.clone()}); data.models.add(new Model[] {model2, model2.clone()});
data.models.add(new Model[]{model3, model3.clone()}); data.models.add(new Model[] {model3, model3.clone()});
save(); save();
} }
public static synchronized void save(){ public static synchronized void save() {
GlobalConfig.putExtra(GlobalConfig.KEY_DS_LAYOUTS, data); GlobalConfig.putExtra(GlobalConfig.KEY_DS_LAYOUTS, data);
} }
public static int getLayoutCount(){ public static int getLayoutCount() {
return data.models.size(); return data.models.size();
} }
public static ConsoleLayout createLayout(int index){ public static ConsoleLayout createLayout(int index) {
index = Math.min(getLayoutCount()-1, index); index = Math.min(getLayoutCount() - 1, index);
return new DsLayout(data.models.get(index)[0],data.models.get(index)[1]); return new DsLayout(data.models.get(index)[0], data.models.get(index)[1]);
} }
private static class DataModel { private static class DataModel {

View file

@ -22,7 +22,7 @@ class Model implements Cloneable {
public Model clone() { public Model clone() {
try { try {
return (Model) super.clone(); return (Model) super.clone();
} catch (Exception e){ } catch (Exception e) {
Log.e(Constants.LOG_TAG, "Error on clone DsModel!", e); Log.e(Constants.LOG_TAG, "Error on clone DsModel!", e);
return new Model(); return new Model();
} }

View file

@ -41,7 +41,7 @@ public class GamesGridView extends RecyclerView {
} }
private void onLongClickGame(GameMetadata game) { private void onLongClickGame(GameMetadata game) {
if (longClickListener != null){ if (longClickListener != null) {
longClickListener.run(game); longClickListener.run(game);
} }
} }

View file

@ -1,152 +0,0 @@
package com.panda3ds.pandroid.view.renderer.layout;
import android.graphics.Rect;
import android.view.Gravity;
import com.panda3ds.pandroid.math.Vector2;
public class RelativeScreenLayout implements ConsoleLayout {
private final Rect topDisplay = new Rect();
private final Rect bottomDisplay = new Rect();
private final Vector2 screenSize = new Vector2(1.0f, 1.0f);
private final Vector2 topSourceSize = new Vector2(1.0f, 1.0f);
private final Vector2 bottomSourceSize = new Vector2(1.0f, 1.0f);
private boolean landscapeReverse = false;
private boolean portraitReverse = false;
private float landscapeSpace = 0.6f;
private int landscapeGravity = Gravity.CENTER;
private int portraitGravity = Gravity.TOP;
@Override
public void update(int screenWidth, int screenHeight) {
screenSize.set(screenWidth, screenHeight);
updateBounds();
}
@Override
public void setBottomDisplaySourceSize(int width, int height) {
bottomSourceSize.set(width, height);
updateBounds();
}
@Override
public void setTopDisplaySourceSize(int width, int height) {
topSourceSize.set(width, height);
updateBounds();
}
public void setPortraitGravity(int portraitGravity) {
this.portraitGravity = portraitGravity;
}
public void setLandscapeGravity(int landscapeGravity) {
this.landscapeGravity = landscapeGravity;
}
public void setLandscapeSpace(float landscapeSpace) {
this.landscapeSpace = landscapeSpace;
}
public void setLandscapeReverse(boolean landscapeReverse) {
this.landscapeReverse = landscapeReverse;
}
public void setPortraitReverse(boolean portraitReverse) {
this.portraitReverse = portraitReverse;
}
private void updateBounds() {
int screenWidth = (int) screenSize.x;
int screenHeight = (int) screenSize.y;
Vector2 topSourceSize = this.topSourceSize;
Vector2 bottomSourceSize = this.bottomSourceSize;
Rect topDisplay = this.topDisplay;
Rect bottomDisplay = this.bottomDisplay;
if ((landscapeReverse && screenWidth > screenHeight) || (portraitReverse && screenWidth < screenHeight)){
topSourceSize = this.bottomSourceSize;
bottomSourceSize = this.topSourceSize;
topDisplay = this.bottomDisplay;
bottomDisplay = this.topDisplay;
}
if (screenWidth > screenHeight) {
int topDisplayWidth = (int) ((screenHeight / topSourceSize.y) * topSourceSize.x);
int topDisplayHeight = screenHeight;
if (topDisplayWidth > (screenWidth * landscapeSpace)) {
topDisplayWidth = (int) (screenWidth * landscapeSpace);
topDisplayHeight = (int) ((topDisplayWidth / topSourceSize.x) * topSourceSize.y);
}
int bottomDisplayHeight = (int) (((screenWidth - topDisplayWidth) / bottomSourceSize.x) * bottomSourceSize.y);
topDisplay.set(0, 0, topDisplayWidth, topDisplayHeight);
bottomDisplay.set(topDisplayWidth, 0, topDisplayWidth + (screenWidth - topDisplayWidth), bottomDisplayHeight);
adjustHorizontalGravity();
} else {
int topScreenHeight = (int) ((screenWidth / topSourceSize.x) * topSourceSize.y);
topDisplay.set(0, 0, screenWidth, topScreenHeight);
int bottomDisplayHeight = (int) ((screenWidth / bottomSourceSize.x) * bottomSourceSize.y);
int bottomDisplayWidth = screenWidth;
int bottomDisplayX = 0;
if (topScreenHeight + bottomDisplayHeight > screenHeight) {
bottomDisplayHeight = (screenHeight - topScreenHeight);
bottomDisplayWidth = (int) ((bottomDisplayHeight / bottomSourceSize.y) * bottomSourceSize.x);
bottomDisplayX = (screenWidth - bottomDisplayX) / 2;
}
topDisplay.set(0, 0, screenWidth, topScreenHeight);
bottomDisplay.set(bottomDisplayX, topScreenHeight, bottomDisplayX + bottomDisplayWidth, topScreenHeight + bottomDisplayHeight);
adjustVerticalGravity();
}
}
private void adjustHorizontalGravity(){
int topOffset = 0;
int bottomOffset = 0;
switch (landscapeGravity){
case Gravity.CENTER:{
topOffset = (int) (screenSize.y - topDisplay.height())/2;
bottomOffset = (int) (screenSize.y - bottomDisplay.height())/2;
}break;
case Gravity.BOTTOM:{
topOffset = (int) (screenSize.y - topDisplay.height());
bottomOffset = (int) (screenSize.y - bottomDisplay.height());
}break;
}
topDisplay.offset(0, topOffset);
bottomDisplay.offset(0, bottomOffset);
}
private void adjustVerticalGravity(){
int height = (topDisplay.height() + bottomDisplay.height());
int space = 0;
switch (portraitGravity){
case Gravity.CENTER:{
space = (int) (screenSize.y - height)/2;
}break;
case Gravity.BOTTOM:{
space = (int) (screenSize.y - height);
}break;
}
topDisplay.offset(0, space);
bottomDisplay.offset(0,space);
}
@Override
public Rect getBottomDisplayBounds() {
return bottomDisplay;
}
@Override
public Rect getTopDisplayBounds() {
return topDisplay;
}
}

View file

@ -1,63 +0,0 @@
package com.panda3ds.pandroid.view.renderer.layout;
import android.graphics.Rect;
import android.view.Gravity;
import com.panda3ds.pandroid.math.Vector2;
public class SingleScreenLayout implements ConsoleLayout {
private final Rect topDisplay = new Rect();
private final Rect bottomDisplay = new Rect();
private final Vector2 screenSize = new Vector2(1.0f, 1.0f);
private final Vector2 topSourceSize = new Vector2(1.0f, 1.0f);
private final Vector2 bottomSourceSize = new Vector2(1.0f, 1.0f);
private boolean top = true;
@Override
public void update(int screenWidth, int screenHeight) {
screenSize.set(screenWidth, screenHeight);
updateBounds();
}
@Override
public void setBottomDisplaySourceSize(int width, int height) {
bottomSourceSize.set(width, height);
updateBounds();
}
@Override
public void setTopDisplaySourceSize(int width, int height) {
topSourceSize.set(width, height);
updateBounds();
}
private void updateBounds() {
int screenWidth = (int) screenSize.x;
int screenHeight = (int) screenSize.y;
Vector2 source = top ? topSourceSize : bottomSourceSize;
Rect dest = top ? topDisplay : bottomDisplay;
int width = Math.round((screenHeight / source.y) * source.x);
int height = screenHeight;
int y = 0;
int x = (screenWidth - width) / 2;
if (width > screenWidth){
width = screenWidth;
height = Math.round((screenWidth / source.x) * source.y);
x = 0;
y = (screenHeight - height)/2;
}
dest.set(x, y, x + width, y+height);
(top ? bottomDisplay : topDisplay).set(0,0,0,0);
}
@Override
public Rect getBottomDisplayBounds() {
return bottomDisplay;
}
@Override
public Rect getTopDisplayBounds() {
return topDisplay;
}
}