mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 07:49:44 +08:00
Made the 'Auto save files' an EXPERIMENTAL feature and disabled by default
Can be enabled from preferences
This commit is contained in:
Generated
+1
@@ -12,6 +12,7 @@
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_github.xml" value="0.21837606837606838" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_linear_layout.xml" value="0.175" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_relative_layout.xml" value="0.175" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_save.xml" value="0.26205128205128203" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_signature_help.xml" value="0.19907407407407407" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/drawable/ic_text_lower.xml" value="0.19907407407407407" />
|
||||
<entry key="..\:/Projects/AndroidStudioProjects/AndroidIDE/app/src/main/res/layout/activity_about.xml" value="0.264" />
|
||||
|
||||
Binary file not shown.
@@ -28,6 +28,7 @@ import android.graphics.drawable.GradientDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.TextUtils;
|
||||
import android.view.Gravity;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
@@ -110,7 +111,6 @@ import com.itsaky.androidide.views.CodeEditorView;
|
||||
import com.itsaky.androidide.views.MaterialBanner;
|
||||
import com.itsaky.androidide.views.SymbolInputView;
|
||||
import com.itsaky.inflater.ILayoutInflater;
|
||||
import com.itsaky.inflater.values.ValuesTable;
|
||||
import com.itsaky.inflater.values.ValuesTableFactory;
|
||||
import com.itsaky.lsp.java.models.JavaServerConfiguration;
|
||||
import com.itsaky.lsp.models.DiagnosticItem;
|
||||
@@ -122,7 +122,6 @@ import com.unnamed.b.atv.model.TreeNode;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -133,6 +132,7 @@ import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -827,7 +827,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
|
||||
public void saveResult (int index, SaveResult result) {
|
||||
if (index >= 0 && index < mViewModel.getOpenedFileCount ()) {
|
||||
var frag = getEditorAtIndex (index);
|
||||
if (frag == null) {
|
||||
if (frag == null || frag.getFile () == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -941,8 +941,13 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
|
||||
var opened = mViewModel.getOpenedFile (index);
|
||||
LOG.info ("Closing file:", opened);
|
||||
final var editor = getEditorAtIndex (index);
|
||||
|
||||
if (editor != null && editor.isModified ()) {
|
||||
notifyFilesUnsaved (Collections.singletonList (editor), () -> closeFile (index));
|
||||
return;
|
||||
}
|
||||
|
||||
if (editor != null && editor.getEditor () != null) {
|
||||
editor.save ();
|
||||
editor.getEditor ().close ();
|
||||
} else {
|
||||
LOG.error ("Cannot save file before close. Editor instance is null");
|
||||
@@ -964,40 +969,80 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
|
||||
|
||||
public void closeAll () {
|
||||
final var count = mViewModel.getOpenedFileCount ();
|
||||
final var unsavedFiles = mViewModel.getOpenedFiles ()
|
||||
.stream ()
|
||||
.map (this::getEditorForFile)
|
||||
.filter (editor -> editor != null && editor.isModified ())
|
||||
.collect (Collectors.toList ());
|
||||
|
||||
// Save and close all files one by one
|
||||
for (int i = 0; i < count; i++) {
|
||||
final var editor = getEditorAtIndex (i);
|
||||
if (editor != null && editor.getEditor () != null) {
|
||||
editor.save ();
|
||||
editor.getEditor ().close ();
|
||||
} else {
|
||||
LOG.error ("Unable to save file at index:", i);
|
||||
if (unsavedFiles.isEmpty ()) {
|
||||
// Files were already saved, close all files one by one
|
||||
for (int i = 0; i < count; i++) {
|
||||
final var editor = getEditorAtIndex (i);
|
||||
if (editor != null && editor.getEditor () != null) {
|
||||
editor.getEditor ().close ();
|
||||
} else {
|
||||
LOG.error ("Unable to close file at index:", i);
|
||||
}
|
||||
}
|
||||
|
||||
mViewModel.removeAllFiles ();
|
||||
mBinding.tabs.removeAllTabs ();
|
||||
mBinding.tabs.requestLayout ();
|
||||
mBinding.editorContainer.removeAllViews ();
|
||||
|
||||
invalidateOptionsMenu ();
|
||||
} else {
|
||||
// There are unsaved files
|
||||
notifyFilesUnsaved (unsavedFiles, this::closeAll);
|
||||
}
|
||||
|
||||
mViewModel.removeAllFiles ();
|
||||
mBinding.tabs.removeAllTabs ();
|
||||
mBinding.tabs.requestLayout ();
|
||||
mBinding.editorContainer.removeAllViews ();
|
||||
|
||||
invalidateOptionsMenu ();
|
||||
}
|
||||
|
||||
private void notifyFilesUnsaved (List<CodeEditorView> unsavedEditors, Runnable invokeAfter) {
|
||||
final var builder = DialogUtils.newYesNoDialog (this,
|
||||
getString (R.string.title_files_unsaved), // title
|
||||
getString (R.string.msg_files_unsaved, TextUtils.join ("\n", unsavedEditors)), // message
|
||||
(dialog, which) -> { // 'yes' click
|
||||
dialog.dismiss ();
|
||||
saveAll (true);
|
||||
invokeAfter.run ();
|
||||
},
|
||||
(dialog, which) -> { // 'no' click
|
||||
dialog.dismiss ();
|
||||
// Mark all the files as saved, then try to close them all
|
||||
for (var editor : unsavedEditors) {
|
||||
editor.markAsSaved ();
|
||||
}
|
||||
|
||||
invokeAfter.run ();
|
||||
});
|
||||
builder.show ();
|
||||
}
|
||||
|
||||
public void closeOthers () {
|
||||
final var file = mViewModel.getCurrentFile ();
|
||||
for (int i = 0; i < mViewModel.getOpenedFileCount (); i++) {
|
||||
final var editor = getEditorAtIndex (i);
|
||||
|
||||
// Index of files changes as we keep close files
|
||||
// So we compare the files instead of index
|
||||
if (editor != null) {
|
||||
if (!file.equals (editor.getFile ())) {
|
||||
closeFile (i);
|
||||
final var unsavedFiles = mViewModel.getOpenedFiles ()
|
||||
.stream ()
|
||||
.map (this::getEditorForFile)
|
||||
.filter (editor -> editor != null && editor.isModified ())
|
||||
.collect (Collectors.toList ());
|
||||
|
||||
if (unsavedFiles.isEmpty ()) {
|
||||
final var file = mViewModel.getCurrentFile ();
|
||||
for (int i = 0; i < mViewModel.getOpenedFileCount (); i++) {
|
||||
final var editor = getEditorAtIndex (i);
|
||||
|
||||
// Index of files changes as we keep close files
|
||||
// So we compare the files instead of index
|
||||
if (editor != null) {
|
||||
if (!file.equals (editor.getFile ())) {
|
||||
closeFile (i);
|
||||
}
|
||||
} else {
|
||||
LOG.error ("Unable to save file at index:", i);
|
||||
}
|
||||
} else {
|
||||
LOG.error ("Unable to save file at index:", i);
|
||||
}
|
||||
} else {
|
||||
notifyFilesUnsaved (unsavedFiles, this::closeOthers);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1019,7 +1064,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
|
||||
public CodeEditorView getEditorForFile (@NonNull final File file) {
|
||||
for (int i = 0; i < mViewModel.getOpenedFileCount (); i++) {
|
||||
final CodeEditorView editor = (CodeEditorView) mBinding.editorContainer.getChildAt (i);
|
||||
if (editor.getFile ().equals (file)) {
|
||||
if (file.equals (editor.getFile ())) {
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
@@ -1157,7 +1202,7 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
|
||||
private void previewLayout () {
|
||||
try {
|
||||
|
||||
if (getCurrentEditor () == null) {
|
||||
if (getCurrentEditor () == null || getCurrentEditor ().getFile () == null) {
|
||||
LOG.error ("No file is opened. Cannot preview layout.");
|
||||
return;
|
||||
}
|
||||
@@ -1498,14 +1543,16 @@ public class EditorActivity extends StudioActivity implements FileTreeFragment.F
|
||||
|
||||
mTabCloseAction.setOnActionItemClickListener ((item) -> {
|
||||
final int id = item.getActionId ();
|
||||
saveAll ();
|
||||
if (getApp ().getPrefManager ().getBoolean (PreferenceManager.KEY_EDITOR_AUTO_SAVE, false)) {
|
||||
saveAll ();
|
||||
}
|
||||
|
||||
if (id == ACTION_ID_CLOSE) {
|
||||
closeFile (mBinding.tabs.getSelectedTabPosition ());
|
||||
}
|
||||
|
||||
if (id == ACTION_ID_OTHERS) {
|
||||
closeOthers ();
|
||||
closeOthers ();
|
||||
}
|
||||
|
||||
if (id == ACTION_ID_ALL) {
|
||||
|
||||
+48
-30
@@ -19,6 +19,8 @@ package com.itsaky.androidide.fragments.preferences;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.SwitchPreference;
|
||||
@@ -33,12 +35,15 @@ import com.itsaky.androidide.utils.DialogUtils;
|
||||
import static com.itsaky.androidide.managers.PreferenceManager.*;
|
||||
import static com.itsaky.androidide.models.PrefBasedJavaServerSettings.*;
|
||||
|
||||
public class EditorPreferences extends BasePreferenceFragment implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener {
|
||||
public class EditorPreferences extends BasePreferenceFragment {
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle p1, String p2) {
|
||||
super.onCreatePreferences(p1, p2);
|
||||
if(getContext() == null) return;
|
||||
|
||||
if(getContext() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final var screen = getPreferenceScreen();
|
||||
final var commonCategory = new PreferenceCategory (getContext ());
|
||||
@@ -48,6 +53,7 @@ public class EditorPreferences extends BasePreferenceFragment implements Prefere
|
||||
final var nonPrintable = new Preference(getContext());
|
||||
final var tabSize = new Preference(getContext());
|
||||
final var drawHex = new SwitchPreference(getContext());
|
||||
final var autoSave = new SwitchPreference (getContext ());
|
||||
|
||||
final var javaMatchLower = new SwitchPreference (getContext ());
|
||||
|
||||
@@ -74,6 +80,11 @@ public class EditorPreferences extends BasePreferenceFragment implements Prefere
|
||||
drawHex.setTitle(R.string.idepref_editor_drawhexcolors_title);
|
||||
drawHex.setSummary(R.string.idepref_editor_drawhexcolors_summary);
|
||||
|
||||
autoSave.setIcon (R.drawable.ic_save);
|
||||
autoSave.setKey (KEY_EDITOR_AUTO_SAVE);
|
||||
autoSave.setTitle (getString(R.string.idepref_editor_autoSave_title));
|
||||
autoSave.setSummary (getString(R.string.idepref_editor_autoSave_summary));
|
||||
|
||||
javaMatchLower.setKey (KEY_JAVA_PREF_MATCH_LOWER);
|
||||
javaMatchLower.setIcon (R.drawable.ic_text_lower);
|
||||
javaMatchLower.setTitle (getString(R.string.idepref_java_matchLower_title));
|
||||
@@ -84,46 +95,55 @@ public class EditorPreferences extends BasePreferenceFragment implements Prefere
|
||||
commonCategory.addPreference(nonPrintable);
|
||||
commonCategory.addPreference(tabSize);
|
||||
commonCategory.addPreference(drawHex);
|
||||
commonCategory.addPreference (autoSave);
|
||||
|
||||
javaCategory.setTitle (getString(R.string.idepref_editor_category_java));
|
||||
javaCategory.addPreference (javaMatchLower);
|
||||
|
||||
setPreferenceScreen(screen);
|
||||
|
||||
fontSize.setOnPreferenceClickListener(this);
|
||||
nonPrintable.setOnPreferenceClickListener(this);
|
||||
tabSize.setOnPreferenceClickListener(this);
|
||||
drawHex.setOnPreferenceChangeListener(this);
|
||||
javaMatchLower.setOnPreferenceChangeListener (this);
|
||||
fontSize.setOnPreferenceClickListener(this::onPreferenceClick);
|
||||
nonPrintable.setOnPreferenceClickListener(this::onPreferenceClick);
|
||||
tabSize.setOnPreferenceClickListener(this::onPreferenceClick);
|
||||
drawHex.setOnPreferenceChangeListener(this::onPreferenceChange);
|
||||
autoSave.setOnPreferenceChangeListener (this::onPreferenceChange);
|
||||
javaMatchLower.setOnPreferenceChangeListener (this::onPreferenceChange);
|
||||
|
||||
drawHex.setChecked(getPrefManager().getBoolean(KEY_EDITOR_DRAW_HEX, true));
|
||||
autoSave.setChecked (getPrefManager ().getBoolean (KEY_EDITOR_AUTO_SAVE, false));
|
||||
javaMatchLower.setChecked (getPrefManager ().getBoolean (KEY_JAVA_PREF_MATCH_LOWER, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
|
||||
public boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
|
||||
final boolean value = (boolean) newValue;
|
||||
if(preference.getKey().equals(KEY_EDITOR_DRAW_HEX)) {
|
||||
getPrefManager().putBoolean(KEY_EDITOR_DRAW_HEX, value);
|
||||
ConstantsBridge.EDITOR_PREF_DRAW_HEX_CHANGED = true;
|
||||
} else if (preference.getKey ().equals (KEY_JAVA_PREF_MATCH_LOWER)) {
|
||||
getPrefManager ().putBoolean (KEY_JAVA_PREF_MATCH_LOWER, value);
|
||||
final var javaServer = StudioApp.getInstance ().getJavaLanguageServer ();
|
||||
javaServer.applySettings (PrefBasedJavaServerSettings.getInstance ());
|
||||
|
||||
switch (preference.getKey ()) {
|
||||
case KEY_EDITOR_DRAW_HEX:
|
||||
ConstantsBridge.EDITOR_PREF_DRAW_HEX_CHANGED = true;
|
||||
break;
|
||||
case KEY_JAVA_PREF_MATCH_LOWER:
|
||||
final var javaServer = StudioApp.getInstance ().getJavaLanguageServer ();
|
||||
javaServer.applySettings (PrefBasedJavaServerSettings.getInstance ());
|
||||
break;
|
||||
}
|
||||
|
||||
getPrefManager ().putBoolean (preference.getKey (), value);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
|
||||
public boolean onPreferenceClick(@NonNull Preference preference) {
|
||||
final String key = preference.getKey();
|
||||
if(key.equals(KEY_EDITOR_FONT_SIZE)) {
|
||||
showTextSizeDialog();
|
||||
} else if(key.equals(KEY_EDITOR_PRINTABLE_CHARS)) {
|
||||
showPrintableCharsDialog();
|
||||
} else if(key.equals(KEY_EDITOR_TAB_SIZE)) {
|
||||
showTabSizeDialog();
|
||||
}
|
||||
switch (key) {
|
||||
case KEY_EDITOR_FONT_SIZE:
|
||||
showTextSizeDialog ();
|
||||
break;
|
||||
case KEY_EDITOR_PRINTABLE_CHARS:
|
||||
showPrintableCharsDialog ();
|
||||
break;
|
||||
case KEY_EDITOR_TAB_SIZE:
|
||||
showTabSizeDialog ();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -170,9 +190,7 @@ public class EditorPreferences extends BasePreferenceFragment implements Prefere
|
||||
float s = binding.slider.getValue();
|
||||
changeTextSize(binding, s);
|
||||
});
|
||||
builder.setNeutralButton(R.string.reset, (p1, p2) -> {
|
||||
changeTextSize(binding, 14);
|
||||
});
|
||||
builder.setNeutralButton(R.string.reset, (p1, p2) -> changeTextSize(binding, 14));
|
||||
builder.setCancelable(false);
|
||||
builder.show();
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/************************************************************************************
|
||||
/*
|
||||
* This file is part of AndroidIDE.
|
||||
*
|
||||
*
|
||||
*
|
||||
* AndroidIDE is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
@@ -16,18 +14,24 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
**************************************************************************************/
|
||||
*/
|
||||
|
||||
|
||||
package com.itsaky.androidide.utils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.itsaky.androidide.app.StudioApp;
|
||||
import com.itsaky.androidide.views.SymbolInputView.Symbol;
|
||||
import java.io.File;
|
||||
|
||||
public class Symbols {
|
||||
|
||||
public static Symbol[] forFile(File file) {
|
||||
public static Symbol[] forFile(@Nullable File file) {
|
||||
if (file == null) {
|
||||
return new Symbol[0];
|
||||
}
|
||||
|
||||
if (file.isFile()) {
|
||||
if (file.getName().endsWith(".java")
|
||||
|| file.getName().endsWith(".gradle"))
|
||||
|
||||
@@ -125,6 +125,15 @@ public class EditorViewModel extends ViewModel {
|
||||
return Objects.requireNonNull (mFiles.getValue ()).size ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of currently opened files.
|
||||
* @return The list of opened files.
|
||||
*/
|
||||
@NonNull
|
||||
public List<File> getOpenedFiles () {
|
||||
return mFiles.getValue () == null ? new ArrayList<> () : mFiles.getValue ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an observer to the list of opened files.
|
||||
* @param lifecycleOwner The lifecycle owner.
|
||||
|
||||
@@ -374,4 +374,12 @@ public class CodeEditorView extends FrameLayout {
|
||||
ValuesTableFactory.syncWithFile (getFile ());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark this files as saved. Even if it not saved.
|
||||
*/
|
||||
public void markAsSaved () {
|
||||
isModified = false;
|
||||
notifySaved ();
|
||||
}
|
||||
}
|
||||
@@ -359,5 +359,9 @@
|
||||
<string name="idepref_java_matchLower_summary">If enabled, then typing a lower case or upper case letters will suggest class names as well as scope members.</string>
|
||||
<string name="idepref_editor_category_common">Common</string>
|
||||
<string name="idepref_editor_category_java">Java</string>
|
||||
<string name="title_files_unsaved">Unsaved files</string>
|
||||
<string name="msg_files_unsaved">Some files are not saved. Would you like to save them before closing? Unsaved files are:\n%s</string>
|
||||
<string name="idepref_editor_autoSave_title">Save before closing files</string>
|
||||
<string name="idepref_editor_autoSave_summary">Save files before closing them. This is an EXPERIMENTAL feature. You are expected to save the files yourself.</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -42,6 +42,7 @@ public class PreferenceManager {
|
||||
public static final String KEY_EDITOR_FONT_SIZE = "idepref_editor_fontSize";
|
||||
public static final String KEY_EDITOR_PRINTABLE_CHARS = "idepref_editor_nonPrintableFlags";
|
||||
public static final String KEY_EDITOR_TAB_SIZE = "idepref_editor_tabSize";
|
||||
public static final String KEY_EDITOR_AUTO_SAVE = "idepref_editor_autoSave";
|
||||
|
||||
public static final String KEY_GRADLE_CMD_STACK_TRACE = "idepref_gradleCmd_stacktrace";
|
||||
public static final String KEY_GRADLE_CMD_DEBUG = "idepref_gradleCmd_debug";
|
||||
|
||||
Reference in New Issue
Block a user