diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/TaskListPane.java b/FCL/src/main/java/com/tungsten/fcl/ui/TaskListPane.java index fcedb595..fd9504bf 100644 --- a/FCL/src/main/java/com/tungsten/fcl/ui/TaskListPane.java +++ b/FCL/src/main/java/com/tungsten/fcl/ui/TaskListPane.java @@ -308,13 +308,13 @@ public final class TaskListPane extends FCLAdapter { FCLTextView title = parent.findViewById(R.id.name); state = parent.findViewById(R.id.state); - bar.progressProperty().bind(task.progressProperty()); + bar.percentProgressProperty().bind(task.progressProperty()); title.setText(task.getName()); state.stringProperty().bind(task.messageProperty()); } public void unbind() { - bar.progressProperty().unbind(); + bar.percentProgressProperty().unbind(); state.stringProperty().unbind(); } diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/manage/VersionSettingPage.java b/FCL/src/main/java/com/tungsten/fcl/ui/manage/VersionSettingPage.java index 36f486d2..e5e2fbfb 100644 --- a/FCL/src/main/java/com/tungsten/fcl/ui/manage/VersionSettingPage.java +++ b/FCL/src/main/java/com/tungsten/fcl/ui/manage/VersionSettingPage.java @@ -5,12 +5,15 @@ import android.view.View; import android.widget.ArrayAdapter; import com.tungsten.fcl.R; +import com.tungsten.fcl.game.FCLGameRepository; import com.tungsten.fcl.setting.Profile; import com.tungsten.fcl.setting.VersionSetting; +import com.tungsten.fcl.util.AndroidUtils; import com.tungsten.fcl.util.FXUtils; import com.tungsten.fcl.util.WeakListenerHolder; import com.tungsten.fclauncher.FCLConfig; import com.tungsten.fclcore.fakefx.beans.InvalidationListener; +import com.tungsten.fclcore.fakefx.beans.binding.Bindings; import com.tungsten.fclcore.fakefx.beans.property.BooleanProperty; import com.tungsten.fclcore.fakefx.beans.property.IntegerProperty; import com.tungsten.fclcore.fakefx.beans.property.SimpleBooleanProperty; @@ -21,6 +24,8 @@ import com.tungsten.fclcore.game.JavaVersion; import com.tungsten.fclcore.game.ProcessPriority; import com.tungsten.fclcore.task.Schedulers; import com.tungsten.fclcore.task.Task; +import com.tungsten.fclcore.util.Lang; +import com.tungsten.fclcore.util.platform.MemoryUtils; import com.tungsten.fcllibrary.component.ui.FCLCommonPage; import com.tungsten.fcllibrary.component.view.FCLCheckBox; import com.tungsten.fcllibrary.component.view.FCLEditText; @@ -60,8 +65,6 @@ public class VersionSettingPage extends FCLCommonPage implements ManageUI.Versio private FCLSeekBar allocateSeekbar; - private FCLProgressBar memoryBar; - private FCLSwitch isolateWorkingDirSwitch; private FCLSwitch beGestureSwitch; private FCLSwitch noGameCheckSwitch; @@ -75,15 +78,11 @@ public class VersionSettingPage extends FCLCommonPage implements ManageUI.Versio private FCLImageButton deleteIconButton; private FCLImageButton controllerButton; - private FCLTextView memoryText; - private FCLTextView memoryInfoText; - private FCLTextView memoryAllocateText; - private final InvalidationListener specificSettingsListener; private final StringProperty selectedVersion = new SimpleStringProperty(); private final BooleanProperty enableSpecificSettings = new SimpleBooleanProperty(false); private final IntegerProperty maxMemory = new SimpleIntegerProperty(); - //private final ObjectProperty memoryStatus = new SimpleObjectProperty<>(OperatingSystem.PhysicalMemoryStatus.INVALID); + private final IntegerProperty usedMemory = new SimpleIntegerProperty(0); private final BooleanProperty modpack = new SimpleBooleanProperty(); public VersionSettingPage(Context context, int id, FCLUILayout parent, int resId, boolean globalSetting) { @@ -111,8 +110,6 @@ public class VersionSettingPage extends FCLCommonPage implements ManageUI.Versio allocateSeekbar = findViewById(R.id.edit_memory); - memoryBar = findViewById(R.id.memory_bar); - FCLSwitch specialSettingSwitch = findViewById(R.id.enable_per_instance_setting); specialSettingSwitch.addCheckedChangeListener(); isolateWorkingDirSwitch = findViewById(R.id.edit_game_dir); @@ -176,9 +173,46 @@ public class VersionSettingPage extends FCLCommonPage implements ManageUI.Versio deleteIconButton.setOnClickListener(this); controllerButton.setOnClickListener(this); - memoryText = findViewById(R.id.memory_text); - memoryInfoText = findViewById(R.id.memory_info_text); - memoryAllocateText = findViewById(R.id.memory_allocate_text); + FCLProgressBar memoryBar = findViewById(R.id.memory_bar); + + FCLTextView memoryStateText = findViewById(R.id.memory_state); + FCLTextView memoryText = findViewById(R.id.memory_text); + FCLTextView memoryInfoText = findViewById(R.id.memory_info_text); + FCLTextView memoryAllocateText = findViewById(R.id.memory_allocate_text); + + memoryStateText.stringProperty().bind(Bindings.createStringBinding(() -> { + if (chkAutoAllocate.isChecked()) { + return getContext().getString(R.string.settings_memory_lower_bound); + } else { + return getContext().getString(R.string.settings_memory); + } + }, chkAutoAllocate.checkProperty())); + + allocateSeekbar.setMax(MemoryUtils.getTotalDeviceMemory(getContext())); + memoryBar.setMax(MemoryUtils.getTotalDeviceMemory(getContext())); + + allocateSeekbar.addProgressListener(); + allocateSeekbar.progressProperty().bindBidirectional(maxMemory); + + memoryText.stringProperty().bind(Bindings.createStringBinding(() -> allocateSeekbar.progressProperty().intValue() + " MB", allocateSeekbar.progressProperty())); + + memoryBar.firstProgressProperty().bind(usedMemory); + memoryBar.secondProgressProperty().bind(Bindings.createIntegerBinding(() -> { + int allocate = (int) (FCLGameRepository.getAllocatedMemory(maxMemory.intValue() * 1024L * 1024L, MemoryUtils.getFreeDeviceMemory(getContext()) * 1024L * 1024L, chkAutoAllocate.isChecked()) / 1024. / 1024); + return usedMemory.intValue() + (chkAutoAllocate.isChecked() ? allocate : maxMemory.intValue()); + }, usedMemory, maxMemory, chkAutoAllocate.checkProperty())); + + memoryInfoText.stringProperty().bind(Bindings.createStringBinding(() -> AndroidUtils.getLocalizedText(getContext(), "settings_memory_used_per_total", MemoryUtils.getUsedDeviceMemory(getContext()) / 1024., MemoryUtils.getTotalDeviceMemory(getContext()) / 1024.), usedMemory)); + + memoryAllocateText.stringProperty().bind(Bindings.createStringBinding(() -> { + long maxMemory = Lang.parseInt(this.maxMemory.get(), 0) * 1024L * 1024L; + return AndroidUtils.getLocalizedText(getContext(), maxMemory / 1024. / 1024. > MemoryUtils.getFreeDeviceMemory(getContext()) + ? (chkAutoAllocate.isChecked() ? "settings_memory_allocate_auto_exceeded" : "settings_memory_allocate_manual_exceeded") + : (chkAutoAllocate.isChecked() ? "settings_memory_allocate_auto" : "settings_memory_allocate_manual"), + maxMemory / 1024. / 1024. / 1024., + FCLGameRepository.getAllocatedMemory(maxMemory, MemoryUtils.getFreeDeviceMemory(getContext()) * 1024L * 1024L, chkAutoAllocate.isChecked()) / 1024. / 1024. / 1024., + MemoryUtils.getFreeDeviceMemory(getContext()) / 1024.); + }, usedMemory, maxMemory, chkAutoAllocate.checkProperty())); settingTypeLayout.setVisibility(globalSetting ? View.GONE : View.VISIBLE); @@ -208,6 +242,12 @@ public class VersionSettingPage extends FCLCommonPage implements ManageUI.Versio return null; } + @Override + public void onResume() { + super.onResume(); + usedMemory.set(MemoryUtils.getUsedDeviceMemory(getContext())); + } + @Override public void loadVersion(Profile profile, String versionId) { this.profile = profile; @@ -222,12 +262,12 @@ public class VersionSettingPage extends FCLCommonPage implements ManageUI.Versio VersionSetting versionSetting = profile.getVersionSetting(versionId); modpack.set(versionId != null && profile.getRepository().isModpack(versionId)); + usedMemory.set(MemoryUtils.getUsedDeviceMemory(getContext())); // unbind data fields if (lastVersionSetting != null) { FXUtils.unbind(txtWidth, lastVersionSetting.widthProperty()); FXUtils.unbind(txtHeight, lastVersionSetting.heightProperty()); - maxMemory.unbindBidirectional(lastVersionSetting.maxMemoryProperty()); FXUtils.unbind(txtJVMArgs, lastVersionSetting.javaArgsProperty()); FXUtils.unbind(txtGameArgs, lastVersionSetting.minecraftArgsProperty()); FXUtils.unbind(txtMetaspace, lastVersionSetting.permSizeProperty()); @@ -241,6 +281,7 @@ public class VersionSettingPage extends FCLCommonPage implements ManageUI.Versio FXUtils.unbindSelection(javaSpinner, lastVersionSetting.javaProperty()); FXUtils.unbindSelection(processPrioritySpinner, lastVersionSetting.processPriorityProperty()); FXUtils.unbindSelection(rendererSpinner, lastVersionSetting.rendererProperty()); + maxMemory.unbindBidirectional(lastVersionSetting.maxMemoryProperty()); lastVersionSetting.usesGlobalProperty().removeListener(specificSettingsListener); } @@ -248,8 +289,6 @@ public class VersionSettingPage extends FCLCommonPage implements ManageUI.Versio // bind new data fields FXUtils.bindInt(txtWidth, versionSetting.widthProperty()); FXUtils.bindInt(txtHeight, versionSetting.heightProperty()); - maxMemory.bindBidirectional(versionSetting.maxMemoryProperty()); - FXUtils.bindString(txtJVMArgs, versionSetting.javaArgsProperty()); FXUtils.bindString(txtGameArgs, versionSetting.minecraftArgsProperty()); FXUtils.bindString(txtMetaspace, versionSetting.permSizeProperty()); @@ -263,6 +302,7 @@ public class VersionSettingPage extends FCLCommonPage implements ManageUI.Versio FXUtils.bindSelection(javaSpinner, versionSetting.javaProperty()); FXUtils.bindSelection(processPrioritySpinner, versionSetting.processPriorityProperty()); FXUtils.bindSelection(rendererSpinner, versionSetting.rendererProperty()); + maxMemory.bindBidirectional(versionSetting.maxMemoryProperty()); versionSetting.usesGlobalProperty().addListener(specificSettingsListener); if (versionId != null) diff --git a/FCL/src/main/java/com/tungsten/fcl/ui/setting/SettingUI.java b/FCL/src/main/java/com/tungsten/fcl/ui/setting/SettingUI.java index d530541b..3a76a5c6 100644 --- a/FCL/src/main/java/com/tungsten/fcl/ui/setting/SettingUI.java +++ b/FCL/src/main/java/com/tungsten/fcl/ui/setting/SettingUI.java @@ -6,6 +6,8 @@ import android.content.Context; import com.google.android.material.tabs.TabLayout; import com.tungsten.fcl.R; +import com.tungsten.fcl.setting.Profiles; +import com.tungsten.fcl.ui.manage.VersionSettingPage; import com.tungsten.fclcore.task.Task; import com.tungsten.fcllibrary.component.ui.FCLBasePage; import com.tungsten.fcllibrary.component.ui.FCLMultiPageUI; @@ -36,6 +38,12 @@ public class SettingUI extends FCLMultiPageUI implements TabLayout.OnTabSelected container.post(this::initPages); } + @Override + public void onStart() { + super.onStart(); + ((VersionSettingPage) pageManager.getPageById(SettingPageManager.PAGE_ID_SETTING_GAME)).loadVersion(Profiles.getSelectedProfile(), null); + } + @Override public void onBackPressed() { if (pageManager != null && pageManager.canReturn()) { @@ -99,6 +107,7 @@ public class SettingUI extends FCLMultiPageUI implements TabLayout.OnTabSelected break; default: pageManager.switchPage(SettingPageManager.PAGE_ID_SETTING_GAME); + ((VersionSettingPage) pageManager.getPageById(SettingPageManager.PAGE_ID_SETTING_GAME)).loadVersion(Profiles.getSelectedProfile(), null); break; } } diff --git a/FCL/src/main/java/com/tungsten/fcl/util/FXUtils.java b/FCL/src/main/java/com/tungsten/fcl/util/FXUtils.java index 51bdc5d7..5ba1d207 100644 --- a/FCL/src/main/java/com/tungsten/fcl/util/FXUtils.java +++ b/FCL/src/main/java/com/tungsten/fcl/util/FXUtils.java @@ -113,7 +113,6 @@ public final class FXUtils { T value = property.getValue(); editText.setText(converter == null ? (String) value : converter.toString(value)); } - editText.fromUserOrSystem = false; } } diff --git a/FCL/src/main/res/layout/page_version_setting.xml b/FCL/src/main/res/layout/page_version_setting.xml index 3f23c83c..dce5f0fb 100644 --- a/FCL/src/main/res/layout/page_version_setting.xml +++ b/FCL/src/main/res/layout/page_version_setting.xml @@ -267,33 +267,24 @@ android:layout_height="wrap_content" style="@style/Widget.AppCompat.ProgressBar.Horizontal"/> - + android:singleLine="true" + app:auto_text_tint="true" + android:text="@string/settings_memory_used_per_total"/> - - - - - + diff --git a/FCLCore/src/main/java/com/tungsten/fclcore/util/platform/MemoryUtils.java b/FCLCore/src/main/java/com/tungsten/fclcore/util/platform/MemoryUtils.java index b7fee551..029cf175 100644 --- a/FCLCore/src/main/java/com/tungsten/fclcore/util/platform/MemoryUtils.java +++ b/FCLCore/src/main/java/com/tungsten/fclcore/util/platform/MemoryUtils.java @@ -3,6 +3,8 @@ package com.tungsten.fclcore.util.platform; import android.app.ActivityManager; import android.content.Context; +import com.tungsten.fclauncher.utils.Architecture; + public class MemoryUtils { public static int getTotalDeviceMemory(Context context) { @@ -12,6 +14,13 @@ public class MemoryUtils { return (int) (memInfo.totalMem / 1048576L); } + public static int getUsedDeviceMemory(Context context) { + ActivityManager actManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo(); + actManager.getMemoryInfo(memInfo); + return (int) ((memInfo.totalMem - memInfo.availMem) / 1048576L); + } + public static int getFreeDeviceMemory(Context context) { ActivityManager actManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); ActivityManager.MemoryInfo memInfo = new ActivityManager.MemoryInfo(); @@ -21,14 +30,14 @@ public class MemoryUtils { public static int findBestRAMAllocation(Context context) { int totalDeviceMemory = getTotalDeviceMemory(context); - if (totalDeviceMemory < 1024) { + if (totalDeviceMemory <= 1024) { return 512; - } else if (totalDeviceMemory < 2048) { - return 1024; - } else if (totalDeviceMemory < 4096) { - return 2048; + } else if (totalDeviceMemory <= 6144) { + return Architecture.is32BitsDevice() ? 768 : 1024; + } else if (totalDeviceMemory <= 12288) { + return Architecture.is32BitsDevice() ? 768 : 2048; } else { - return 4096; + return Architecture.is32BitsDevice() ? 768 : 4096; } } diff --git a/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLCheckBox.java b/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLCheckBox.java index 19ff1ae6..54711a5f 100644 --- a/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLCheckBox.java +++ b/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLCheckBox.java @@ -64,6 +64,7 @@ public class FCLCheckBox extends AppCompatCheckBox { setOnCheckedChangeListener((compoundButton, b) -> { fromUserOrSystem = true; checkProperty().set(b); + fromUserOrSystem = false; }); } @@ -146,7 +147,6 @@ public class FCLCheckBox extends AppCompatCheckBox { boolean isCheck = get(); setChecked(isCheck); } - fromUserOrSystem = false; }); } diff --git a/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLEditText.java b/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLEditText.java index 0c5a8bd1..4059d84f 100644 --- a/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLEditText.java +++ b/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLEditText.java @@ -115,6 +115,7 @@ public class FCLEditText extends AppCompatEditText { public void afterTextChanged(Editable editable) { fromUserOrSystem = true; stringProperty().set(getText().toString()); + fromUserOrSystem = false; } }); } diff --git a/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLProgressBar.java b/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLProgressBar.java index 74b3dbcb..3a346256 100644 --- a/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLProgressBar.java +++ b/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLProgressBar.java @@ -17,6 +17,8 @@ import com.tungsten.fcllibrary.component.theme.ThemeEngine; public class FCLProgressBar extends ProgressBar { private DoubleProperty progress; + private IntegerProperty firstProgressProperty; + private IntegerProperty secondProgressProperty; private BooleanProperty visibilityProperty; private BooleanProperty disableProperty; @@ -34,6 +36,7 @@ public class FCLProgressBar extends ProgressBar { ThemeEngine.getInstance().getTheme().getDkColor() }; setProgressTintList(new ColorStateList(state, color)); + setSecondaryProgressTintList(new ColorStateList(state, color)); setIndeterminateTintList(new ColorStateList(state, color)); } @@ -68,11 +71,7 @@ public class FCLProgressBar extends ProgressBar { theme.bind(ThemeEngine.getInstance().getTheme().colorProperty()); } - public final void setProgressValue(double progress) { - progressProperty().set(progress); - } - - public final DoubleProperty progressProperty() { + public final DoubleProperty percentProgressProperty() { if (progress == null) { progress = new DoublePropertyBase() { @@ -92,7 +91,7 @@ public class FCLProgressBar extends ProgressBar { } public String getName() { - return "progress"; + return "percentProgress"; } }; } @@ -100,6 +99,58 @@ public class FCLProgressBar extends ProgressBar { return progress; } + public final IntegerProperty firstProgressProperty() { + if (firstProgressProperty == null) { + firstProgressProperty = new IntegerPropertyBase() { + + public void invalidated() { + Schedulers.androidUIThread().execute(() -> { + int progress = get(); + if (progress >= 0) { + setProgress(Math.min(progress, getMax())); + } + }); + } + + public Object getBean() { + return this; + } + + public String getName() { + return "firstProgress"; + } + }; + } + + return firstProgressProperty; + } + + public final IntegerProperty secondProgressProperty() { + if (secondProgressProperty == null) { + secondProgressProperty = new IntegerPropertyBase() { + + public void invalidated() { + Schedulers.androidUIThread().execute(() -> { + int progress = get(); + if (progress >= 0) { + setSecondaryProgress(Math.min(progress, getMax())); + } + }); + } + + public Object getBean() { + return this; + } + + public String getName() { + return "secondProgress"; + } + }; + } + + return secondProgressProperty; + } + public final void setVisibilityValue(boolean visibility) { visibilityProperty().set(visibility); } diff --git a/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLSeekBar.java b/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLSeekBar.java index 079ab4a2..1c8b5b06 100644 --- a/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLSeekBar.java +++ b/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLSeekBar.java @@ -3,6 +3,7 @@ package com.tungsten.fcllibrary.component.view; import android.content.Context; import android.content.res.ColorStateList; import android.util.AttributeSet; +import android.widget.SeekBar; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -17,8 +18,10 @@ import com.tungsten.fcllibrary.component.theme.ThemeEngine; public class FCLSeekBar extends AppCompatSeekBar { + private boolean fromUserOrSystem = false; private BooleanProperty visibilityProperty; private BooleanProperty disableProperty; + private IntegerProperty progressProperty; private final IntegerProperty theme = new IntegerPropertyBase() { @@ -48,6 +51,27 @@ public class FCLSeekBar extends AppCompatSeekBar { } }; + public void addProgressListener() { + setOnSeekBarChangeListener(new OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int i, boolean b) { + fromUserOrSystem = true; + progressProperty().set(i); + fromUserOrSystem = false; + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } + }); + } + public FCLSeekBar(@NonNull Context context) { super(context); theme.bind(ThemeEngine.getInstance().getTheme().colorProperty()); @@ -127,4 +151,38 @@ public class FCLSeekBar extends AppCompatSeekBar { return disableProperty; } + public final void setProgressValue(int progressValue) { + progressProperty().set(progressValue); + } + + public final int getProgressValue() { + return progressProperty == null ? -1 : progressProperty().get(); + } + + public final IntegerProperty progressProperty() { + if (progressProperty == null) { + progressProperty = new IntegerPropertyBase() { + + public void invalidated() { + Schedulers.androidUIThread().execute(() -> { + if (!fromUserOrSystem) { + int progress = get(); + setProgress(progress); + } + }); + } + + public Object getBean() { + return this; + } + + public String getName() { + return "progress"; + } + }; + } + + return progressProperty; + } + } diff --git a/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLSpinner.java b/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLSpinner.java index 1df9caab..fd729d8d 100644 --- a/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLSpinner.java +++ b/FCLLibrary/src/main/java/com/tungsten/fcllibrary/component/view/FCLSpinner.java @@ -29,6 +29,7 @@ public class FCLSpinner extends AppCompatSpinner { if (dataList != null && dataList.size() > i) { fromUserOrSystem = true; selectedItemProperty().set(dataList.get(i)); + fromUserOrSystem = false; } } @@ -85,7 +86,6 @@ public class FCLSpinner extends AppCompatSpinner { T data = get(); setSelection(dataList.indexOf(data)); } - fromUserOrSystem = false; }); }