The reverse of @{link #getFileForDocId}.
- */
- private static String getDocIdForFile(File file) {
- return file.getAbsolutePath();
- }
-
- /** Get the file given a document id (the reverse of {@link #getDocIdForFile(File)}). */
- private static File getFileForDocId(String docId) throws FileNotFoundException {
- final File f = new File(docId);
- if (!f.exists()) throw new FileNotFoundException(f.getAbsolutePath() + " not found");
- return f;
- }
-
- private static String getMimeType(File file) {
- if (file.isDirectory()) {
- return Document.MIME_TYPE_DIR;
- } else {
- final String name = file.getName();
- final int lastDot = name.lastIndexOf('.');
- if (lastDot >= 0) {
- final String extension = name.substring(lastDot + 1).toLowerCase(Locale.ROOT);
- final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
- if (mime != null) return mime;
- }
- return "application/octet-stream";
- }
- }
-
- @Override
- public Cursor queryRoots(String[] projection) {
- final MatrixCursor result =
- new MatrixCursor(projection != null ? projection : DEFAULT_ROOT_PROJECTION);
- final String applicationName = getContext().getString(R.string.app_name);
-
- final MatrixCursor.RowBuilder row = result.newRow();
- LOG.debug("queryRoots() before all add");
- row.add(Root.COLUMN_ROOT_ID, getDocIdForFile(BASE_DIR));
- LOG.debug("queryRoots() before all add, 1");
- row.add(Root.COLUMN_DOCUMENT_ID, getDocIdForFile(BASE_DIR));
- LOG.debug("queryRoots() before all add, 2");
- row.add(Root.COLUMN_SUMMARY, null);
- LOG.debug("queryRoots() before all add, 3");
- row.add(
- Root.COLUMN_FLAGS,
- Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD);
- LOG.debug("queryRoots() before all add, 4");
- row.add(Root.COLUMN_TITLE, applicationName);
- LOG.debug("queryRoots() before all add, 5");
- row.add(Root.COLUMN_MIME_TYPES, ALL_MIME_TYPES);
- LOG.debug("queryRoots() before all add, 6");
- row.add(Root.COLUMN_AVAILABLE_BYTES, BASE_DIR.getFreeSpace());
- LOG.debug("queryRoots() before all add, 7");
- row.add(Root.COLUMN_ICON, R.mipmap.ic_launcher);
- LOG.debug("queryRoots() before all add");
- return result;
- }
-
- @Override
- public Cursor queryDocument(String documentId, String[] projection) throws FileNotFoundException {
- final MatrixCursor result =
- new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
- includeFile(result, documentId, null);
- return result;
- }
-
- @Override
- public Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder)
- throws FileNotFoundException {
- final MatrixCursor result =
- new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
- final File parent = getFileForDocId(parentDocumentId);
- for (File file : parent.listFiles()) {
- includeFile(result, null, file);
- }
- return result;
- }
-
- @Override
- public ParcelFileDescriptor openDocument(
- final String documentId, String mode, CancellationSignal signal)
- throws FileNotFoundException {
- final File file = getFileForDocId(documentId);
- final int accessMode = ParcelFileDescriptor.parseMode(mode);
- return ParcelFileDescriptor.open(file, accessMode);
- }
-
- @Override
- public AssetFileDescriptor openDocumentThumbnail(
- String documentId, Point sizeHint, CancellationSignal signal) throws FileNotFoundException {
- final File file = getFileForDocId(documentId);
- final ParcelFileDescriptor pfd =
- ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
- return new AssetFileDescriptor(pfd, 0, file.length());
- }
-
@Override
public boolean onCreate() {
return true;
}
+ @Override
+ public boolean isChildDocument(String parentDocumentId, String documentId) {
+ return documentId.startsWith(parentDocumentId);
+ }
+
@Override
public String createDocument(String parentDocumentId, String mimeType, String displayName)
throws FileNotFoundException {
@@ -231,9 +137,62 @@ public class IDEDocumentsProvider extends DocumentsProvider {
}
@Override
- public String getDocumentType(String documentId) throws FileNotFoundException {
- File file = getFileForDocId(documentId);
- return getMimeType(file);
+ public Cursor queryRoots(String[] projection) {
+ final MatrixCursor result =
+ new MatrixCursor(projection != null ? projection : DEFAULT_ROOT_PROJECTION);
+ final String applicationName = getContext().getString(R.string.app_name);
+
+ final MatrixCursor.RowBuilder row = result.newRow();
+ LOG.debug("queryRoots() before all add");
+ row.add(Root.COLUMN_ROOT_ID, getDocIdForFile(BASE_DIR));
+ LOG.debug("queryRoots() before all add, 1");
+ row.add(Root.COLUMN_DOCUMENT_ID, getDocIdForFile(BASE_DIR));
+ LOG.debug("queryRoots() before all add, 2");
+ row.add(Root.COLUMN_SUMMARY, null);
+ LOG.debug("queryRoots() before all add, 3");
+ row.add(
+ Root.COLUMN_FLAGS,
+ Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD);
+ LOG.debug("queryRoots() before all add, 4");
+ row.add(Root.COLUMN_TITLE, applicationName);
+ LOG.debug("queryRoots() before all add, 5");
+ row.add(Root.COLUMN_MIME_TYPES, ALL_MIME_TYPES);
+ LOG.debug("queryRoots() before all add, 6");
+ row.add(Root.COLUMN_AVAILABLE_BYTES, BASE_DIR.getFreeSpace());
+ LOG.debug("queryRoots() before all add, 7");
+ row.add(Root.COLUMN_ICON, R.mipmap.ic_launcher);
+ LOG.debug("queryRoots() before all add");
+ return result;
+ }
+
+ /**
+ * Get the document id given a file. This document id must be consistent across time as other
+ * applications may save the ID and use it to reference documents later.
+ *
+ * The reverse of @{link #getFileForDocId}.
+ */
+ private static String getDocIdForFile(File file) {
+ return file.getAbsolutePath();
+ }
+
+ @Override
+ public Cursor queryDocument(String documentId, String[] projection) throws FileNotFoundException {
+ final MatrixCursor result =
+ new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
+ includeFile(result, documentId, null);
+ return result;
+ }
+
+ @Override
+ public Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder)
+ throws FileNotFoundException {
+ final MatrixCursor result =
+ new MatrixCursor(projection != null ? projection : DEFAULT_DOCUMENT_PROJECTION);
+ final File parent = getFileForDocId(parentDocumentId);
+ for (File file : parent.listFiles()) {
+ includeFile(result, null, file);
+ }
+ return result;
}
@Override
@@ -277,8 +236,27 @@ public class IDEDocumentsProvider extends DocumentsProvider {
}
@Override
- public boolean isChildDocument(String parentDocumentId, String documentId) {
- return documentId.startsWith(parentDocumentId);
+ public String getDocumentType(String documentId) throws FileNotFoundException {
+ File file = getFileForDocId(documentId);
+ return getMimeType(file);
+ }
+
+ @Override
+ public ParcelFileDescriptor openDocument(
+ final String documentId, String mode, CancellationSignal signal)
+ throws FileNotFoundException {
+ final File file = getFileForDocId(documentId);
+ final int accessMode = ParcelFileDescriptor.parseMode(mode);
+ return ParcelFileDescriptor.open(file, accessMode);
+ }
+
+ @Override
+ public AssetFileDescriptor openDocumentThumbnail(
+ String documentId, Point sizeHint, CancellationSignal signal) throws FileNotFoundException {
+ final File file = getFileForDocId(documentId);
+ final ParcelFileDescriptor pfd =
+ ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
+ return new AssetFileDescriptor(pfd, 0, file.length());
}
/**
@@ -317,4 +295,26 @@ public class IDEDocumentsProvider extends DocumentsProvider {
row.add(Document.COLUMN_FLAGS, flags);
row.add(Document.COLUMN_ICON, R.mipmap.ic_launcher);
}
+
+ /** Get the file given a document id (the reverse of {@link #getDocIdForFile(File)}). */
+ private static File getFileForDocId(String docId) throws FileNotFoundException {
+ final File f = new File(docId);
+ if (!f.exists()) throw new FileNotFoundException(f.getAbsolutePath() + " not found");
+ return f;
+ }
+
+ private static String getMimeType(File file) {
+ if (file.isDirectory()) {
+ return Document.MIME_TYPE_DIR;
+ } else {
+ final String name = file.getName();
+ final int lastDot = name.lastIndexOf('.');
+ if (lastDot >= 0) {
+ final String extension = name.substring(lastDot + 1).toLowerCase(Locale.ROOT);
+ final String mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
+ if (mime != null) return mime;
+ }
+ return "application/octet-stream";
+ }
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/BaseFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/BaseFragment.java
index a4b757f11..debf39a82 100755
--- a/app/src/main/java/com/itsaky/androidide/fragments/BaseFragment.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/BaseFragment.java
@@ -20,9 +20,6 @@
package com.itsaky.androidide.fragments;
-import abhishekti7.unicorn.filepicker.UnicornFilePicker;
-import abhishekti7.unicorn.filepicker.ui.FilePickerActivity;
-
import android.app.Activity;
import android.content.Intent;
import android.os.Environment;
@@ -41,31 +38,12 @@ import com.itsaky.toaster.Toaster;
import java.io.File;
import java.util.ArrayList;
+import abhishekti7.unicorn.filepicker.UnicornFilePicker;
+import abhishekti7.unicorn.filepicker.ui.FilePickerActivity;
+
public class BaseFragment extends Fragment {
private FileChoserCallback dirCallback;
-
- protected StudioActivity getStudioActivity() {
- return (StudioActivity) getActivity();
- }
-
- protected void pickDirectory(FileChoserCallback dirCallback) {
- this.dirCallback = dirCallback;
- UnicornFilePicker.from(this)
- .addConfigBuilder()
- .addItemDivider(false)
- .selectMultipleFiles(false)
- .setRootDirectory(Environment.getExternalStorageDirectory().getAbsolutePath())
- .showHiddenFiles(true)
- .showOnlyDirectory(true)
- .theme(R.style.AppTheme_FilePicker)
- .build();
- Intent intent = new Intent(requireActivity(), FilePickerActivity.class);
-
- // .forResult(abhishekti7.unicorn.filepicker.utils.Constants.REQ_UNICORN_FILE);
- startForResult.launch(intent);
- }
-
ActivityResultLauncher startForResult =
registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
@@ -95,6 +73,27 @@ public class BaseFragment extends Fragment {
}
});
+ protected StudioActivity getStudioActivity() {
+ return (StudioActivity) getActivity();
+ }
+
+ protected void pickDirectory(FileChoserCallback dirCallback) {
+ this.dirCallback = dirCallback;
+ UnicornFilePicker.from(this)
+ .addConfigBuilder()
+ .addItemDivider(false)
+ .selectMultipleFiles(false)
+ .setRootDirectory(Environment.getExternalStorageDirectory().getAbsolutePath())
+ .showHiddenFiles(true)
+ .showOnlyDirectory(true)
+ .theme(R.style.AppTheme_FilePicker)
+ .build();
+ Intent intent = new Intent(requireActivity(), FilePickerActivity.class);
+
+ // .forResult(abhishekti7.unicorn.filepicker.utils.Constants.REQ_UNICORN_FILE);
+ startForResult.launch(intent);
+ }
+
interface FileChoserCallback {
void picketDictionary(File file);
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/DiagnosticsListFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/DiagnosticsListFragment.java
index bb5b2a912..970560321 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/DiagnosticsListFragment.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/DiagnosticsListFragment.java
@@ -70,6 +70,14 @@ public class DiagnosticsListFragment extends Fragment {
unsavedAdapter = null;
}
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ unsavedAdapter = null;
+ list = null;
+ emptyView = null;
+ }
+
public void setAdapter(@NonNull DiagnosticsAdapter adapter) {
if (list != null) {
list.setAdapter(adapter);
@@ -84,12 +92,4 @@ public class DiagnosticsListFragment extends Fragment {
list.setVisibility(error ? View.GONE : View.VISIBLE);
}
}
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- unsavedAdapter = null;
- list = null;
- emptyView = null;
- }
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/FileTreeFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/FileTreeFragment.java
index d11fe6506..59d7aac06 100755
--- a/app/src/main/java/com/itsaky/androidide/fragments/FileTreeFragment.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/FileTreeFragment.java
@@ -95,6 +95,14 @@ public class FileTreeFragment extends BottomSheetDialogFragment
}
}
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ binding = null;
+ mFileTreeView = null;
+ mFileActionListener = null;
+ }
+
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -201,12 +209,6 @@ public class FileTreeFragment extends BottomSheetDialogFragment
__ -> finalWhenDone.run());
}
- private void updateChevron(@NonNull TreeNode node) {
- if (node.getViewHolder() instanceof FileTreeViewHolder) {
- ((FileTreeViewHolder) node.getViewHolder()).updateChevron(!node.isExpanded());
- }
- }
-
private void getNodeFromFiles(File[] files, TreeNode parent) {
Arrays.sort(files, new FileTreeCallable.SortFileName());
Arrays.sort(files, new FileTreeCallable.SortFolder());
@@ -217,6 +219,12 @@ public class FileTreeFragment extends BottomSheetDialogFragment
}
}
+ private void updateChevron(@NonNull TreeNode node) {
+ if (node.getViewHolder() instanceof FileTreeViewHolder) {
+ ((FileTreeViewHolder) node.getViewHolder()).updateChevron(!node.isExpanded());
+ }
+ }
+
@Override
public boolean onLongClick(TreeNode node, Object value) {
if (mFileActionListener != null) {
@@ -332,14 +340,6 @@ public class FileTreeFragment extends BottomSheetDialogFragment
}
}
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- binding = null;
- mFileTreeView = null;
- mFileActionListener = null;
- }
-
public interface FileActionListener {
CodeEditorView openFile(File file);
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/LogFragments.kt b/app/src/main/java/com/itsaky/androidide/fragments/LogFragments.kt
index 946e758f0..67972e73d 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/LogFragments.kt
+++ b/app/src/main/java/com/itsaky/androidide/fragments/LogFragments.kt
@@ -24,30 +24,30 @@ import com.itsaky.androidide.utils.ILogger
* @author Akash Yadav
*/
class IDELogFragment : LogViewFragment() {
- private var logListener: ILogger.LogListener? =
- ILogger.LogListener { priority, tag, message ->
- if (message.contains("\n")) {
- val split = message.split("\n").toTypedArray()
- for (line in split) {
- logLine(priority, tag, line)
- }
- } else {
- logLine(priority, tag, message)
- }
+ private var logListener: ILogger.LogListener? =
+ ILogger.LogListener { priority, tag, message ->
+ if (message.contains("\n")) {
+ val split = message.split("\n").toTypedArray()
+ for (line in split) {
+ logLine(priority, tag, line)
}
-
- init {
- ILogger.addLogListener(this.logListener)
+ } else {
+ logLine(priority, tag, message)
+ }
}
- override fun isSimpleFormattingEnabled() = true
- override fun getLogType() = "ide_logs"
+ init {
+ ILogger.addLogListener(this.logListener)
+ }
- override fun onDestroy() {
- super.onDestroy()
- ILogger.removeLogListener(logListener)
- logListener = null
- }
+ override fun isSimpleFormattingEnabled() = true
+ override fun getLogType() = "ide_logs"
+
+ override fun onDestroy() {
+ super.onDestroy()
+ ILogger.removeLogListener(logListener)
+ logListener = null
+ }
}
/**
@@ -55,6 +55,6 @@ class IDELogFragment : LogViewFragment() {
* @author Akash Yadav
*/
class AppLogFragment : LogViewFragment() {
- override fun isSimpleFormattingEnabled() = false
- override fun getLogType() = "app_logs"
+ override fun isSimpleFormattingEnabled() = false
+ override fun getLogType() = "app_logs"
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/LogViewFragment.kt b/app/src/main/java/com/itsaky/androidide/fragments/LogViewFragment.kt
index ea9eaf60b..debd47151 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/LogViewFragment.kt
+++ b/app/src/main/java/com/itsaky/androidide/fragments/LogViewFragment.kt
@@ -55,7 +55,7 @@ abstract class LogViewFragment : Fragment() {
if (!lineString.endsWith("\n")) {
lineString += "\n"
}
-
+
ThreadUtils.runOnUiThread { this.binding!!.editor.append(lineString) }
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/MainFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/MainFragment.java
index b28e4e499..7262ba93b 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/MainFragment.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/MainFragment.java
@@ -1,34 +1,22 @@
package com.itsaky.androidide.fragments;
-import abhishekti7.unicorn.filepicker.UnicornFilePicker;
-import abhishekti7.unicorn.filepicker.ui.FilePickerActivity;
-
-import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
-import android.os.Environment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-
-import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.itsaky.androidide.EditorActivity;
import com.itsaky.androidide.PreferencesActivity;
import com.itsaky.androidide.R;
import com.itsaky.androidide.TerminalActivity;
-import com.itsaky.androidide.app.StudioApp;
import com.itsaky.androidide.databinding.FragmentMainBinding;
import com.itsaky.androidide.projects.ProjectManager;
-import com.itsaky.androidide.utils.DialogUtils;
-import com.itsaky.toaster.Toaster;
import java.io.File;
-import java.util.ArrayList;
public class MainFragment extends BaseFragment
implements WizardFragment.OnProjectCreatedListener, View.OnClickListener {
@@ -97,13 +85,13 @@ public class MainFragment extends BaseFragment
.commit();
}
- private void gotoSettings() {
- startActivity(new Intent(requireActivity(), PreferencesActivity.class));
- }
-
@Override
public void openProject(@NonNull File root) {
ProjectManager.INSTANCE.setProjectPath(root.getAbsolutePath());
startActivity(new Intent(requireActivity(), EditorActivity.class));
}
+
+ private void gotoSettings() {
+ startActivity(new Intent(requireActivity(), PreferencesActivity.class));
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/NonEditableEditorFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/NonEditableEditorFragment.java
index 284f9735c..016748e95 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/NonEditableEditorFragment.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/NonEditableEditorFragment.java
@@ -64,6 +64,12 @@ public abstract class NonEditableEditorFragment extends Fragment {
editor.setColorScheme(new SchemeAndroidIDE());
}
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ binding = null;
+ }
+
@Nullable
public IDEEditor getEditor() {
if (binding == null) {
@@ -71,10 +77,4 @@ public abstract class NonEditableEditorFragment extends Fragment {
}
return binding.editor;
}
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- binding = null;
- }
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/SearchResultFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/SearchResultFragment.java
index a76486540..8bbb0e514 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/SearchResultFragment.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/SearchResultFragment.java
@@ -68,6 +68,14 @@ public class SearchResultFragment extends Fragment {
unsavedAdapter = null;
}
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ unsavedAdapter = null;
+ list = null;
+ emptyView = null;
+ }
+
public void setAdapter(@NonNull final SearchListAdapter adapter) {
if (list == null) {
unsavedAdapter = adapter;
@@ -82,12 +90,4 @@ public class SearchResultFragment extends Fragment {
list.setVisibility(error ? View.GONE : View.VISIBLE);
}
}
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- unsavedAdapter = null;
- list = null;
- emptyView = null;
- }
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/WizardFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/WizardFragment.java
index ed98d3d5c..e27088431 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/WizardFragment.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/WizardFragment.java
@@ -19,7 +19,6 @@ import androidx.transition.TransitionManager;
import com.google.android.material.transition.MaterialFadeThrough;
import com.google.android.material.transition.MaterialSharedAxis;
-
import com.itsaky.androidide.R;
import com.itsaky.androidide.adapters.WizardTemplateAdapter;
import com.itsaky.androidide.app.StudioApp;
@@ -68,9 +67,6 @@ public class WizardFragment extends BaseFragment {
private OnProjectCreatedListener mListener;
private boolean mLast;
- private int minSdkIndex;
- private int targetSdkIndex;
-
private final OnBackPressedCallback onBackPressedCallback =
new OnBackPressedCallback(true) {
@Override
@@ -78,6 +74,8 @@ public class WizardFragment extends BaseFragment {
onNavigateBack();
}
};
+ private int minSdkIndex;
+ private int targetSdkIndex;
@Nullable
@Override
@@ -171,12 +169,6 @@ public class WizardFragment extends BaseFragment {
initDetailsView();
}
- @Override
- public void onDestroy() {
- super.onDestroy();
- onBackPressedCallback.setEnabled(false);
- }
-
@Override
public void onDestroyView() {
super.onDestroyView();
@@ -190,6 +182,28 @@ public class WizardFragment extends BaseFragment {
mProgressSheet = null;
}
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ onBackPressedCallback.setEnabled(false);
+ }
+
+ public void onSuccess(File root) {
+ if (mProgressSheet != null && mProgressSheet.isShowing()) {
+ mProgressSheet.dismiss();
+ }
+ StudioApp.getInstance().toast(R.string.project_created_successfully, Toaster.Type.SUCCESS);
+
+ if (mListener != null) {
+ getParentFragmentManager().popBackStack();
+ mListener.openProject(root);
+ }
+ }
+
+ public void setOnProjectCreatedListener(OnProjectCreatedListener listener) {
+ mListener = listener;
+ }
+
private String getSelectedItem(int pos, AutoCompleteTextView view) {
return view.getAdapter().getItem(pos).toString();
}
@@ -516,18 +530,6 @@ public class WizardFragment extends BaseFragment {
setSaveLocation();
}
- public void onSuccess(File root) {
- if (mProgressSheet != null && mProgressSheet.isShowing()) {
- mProgressSheet.dismiss();
- }
- StudioApp.getInstance().toast(R.string.project_created_successfully, Toaster.Type.SUCCESS);
-
- if (mListener != null) {
- getParentFragmentManager().popBackStack();
- mListener.openProject(root);
- }
- }
-
private void createProgressSheet() {
mProgressSheet = new ProgressSheet();
mProgressSheet.setShowShadow(false);
@@ -554,8 +556,4 @@ public class WizardFragment extends BaseFragment {
public interface OnProjectCreatedListener {
void openProject(File project);
}
-
- public void setOnProjectCreatedListener(OnProjectCreatedListener listener) {
- mListener = listener;
- }
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/AbstractReferenceEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/AbstractReferenceEditor.java
index cda03ea3e..cb52a09bf 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/attr/AbstractReferenceEditor.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/AbstractReferenceEditor.java
@@ -41,15 +41,6 @@ public abstract class AbstractReferenceEditor extends BaseValueEditorFragment {
private static final ILogger LOG = ILogger.newInstance("ReferenceEditor");
public TextWatcherAdapter resInputWatcher;
- @Override
- protected void notifyValueChanged(@NonNull String newValue) {
- try {
- super.notifyValueChanged(newValue);
- } catch (Throwable e) {
- LOG.error("Unable to update resource value to '" + newValue + "'", e);
- }
- }
-
protected void setupReferenceInput(MaterialAutoCompleteTextView referenceInput) {
Objects.requireNonNull(referenceInput);
@@ -78,6 +69,15 @@ public abstract class AbstractReferenceEditor extends BaseValueEditorFragment {
.whenComplete((list, error) -> handleAutoCompleteResult(list, error, referenceInput));
}
+ @Override
+ protected void notifyValueChanged(@NonNull String newValue) {
+ try {
+ super.notifyValueChanged(newValue);
+ } catch (Throwable e) {
+ LOG.error("Unable to update resource value to '" + newValue + "'", e);
+ }
+ }
+
protected void handleAutoCompleteResult(
List list, Throwable error, AutoCompleteTextView referenceInput) {
if (list == null || list.isEmpty()) {
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/ColorEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/ColorEditor.java
index b4cc6379f..a4d5bf513 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/attr/ColorEditor.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/ColorEditor.java
@@ -18,7 +18,6 @@
package com.itsaky.androidide.fragments.attr;
import android.app.Dialog;
-import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -77,28 +76,6 @@ public class ColorEditor extends AbstractReferenceEditor {
}
}
- @Override
- protected List computeReferenceItems() {
- final var list = new ArrayList();
- final var tables = ValuesTableFactory.getAllTables();
- for (var entry : tables.entrySet()) {
- final var dimens = entry.getValue().getTable("color");
- if (dimens != null) {
- list.addAll(dimens.keySet().stream().map("@color/"::concat).collect(Collectors.toSet()));
- }
- }
-
- list.addAll(
- FrameworkValues.listColors().stream()
- .map("@android:color/"::concat)
- .collect(Collectors.toList()));
-
- final var resTable = StudioApp.getInstance().getResourceTable();
- list.addAll(resTable.listResourceNames("color"));
-
- return list;
- }
-
private Dialog getColorPickerDialog() {
if (colorPickerDialog == null) {
@@ -122,4 +99,26 @@ public class ColorEditor extends AbstractReferenceEditor {
return colorPickerDialog;
}
+
+ @Override
+ protected List computeReferenceItems() {
+ final var list = new ArrayList();
+ final var tables = ValuesTableFactory.getAllTables();
+ for (var entry : tables.entrySet()) {
+ final var dimens = entry.getValue().getTable("color");
+ if (dimens != null) {
+ list.addAll(dimens.keySet().stream().map("@color/"::concat).collect(Collectors.toSet()));
+ }
+ }
+
+ list.addAll(
+ FrameworkValues.listColors().stream()
+ .map("@android:color/"::concat)
+ .collect(Collectors.toList()));
+
+ final var resTable = StudioApp.getInstance().getResourceTable();
+ list.addAll(resTable.listResourceNames("color"));
+
+ return list;
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/attr/FlagEditor.java b/app/src/main/java/com/itsaky/androidide/fragments/attr/FlagEditor.java
index e20a42c46..fa9088ab5 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/attr/FlagEditor.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/attr/FlagEditor.java
@@ -63,6 +63,13 @@ public class FlagEditor extends FixedValueEditor {
// Does noting...
}
+ @Override
+ protected Chip newChip(String title, boolean checked) {
+ final var chip = super.newChip(title, checked);
+ chip.setOnCheckedChangeListener(this::onCheckChangedMultiple);
+ return chip;
+ }
+
protected void onCheckChangedMultiple(CompoundButton compoundButton, boolean b) {
final var items = new ArrayList();
for (var id : this.chipGroup.getCheckedChipIds()) {
@@ -78,11 +85,4 @@ public class FlagEditor extends FixedValueEditor {
notifyValueChanged(TextUtils.join("|", items));
}
-
- @Override
- protected Chip newChip(String title, boolean checked) {
- final var chip = super.newChip(title, checked);
- chip.setOnCheckedChangeListener(this::onCheckChangedMultiple);
- return chip;
- }
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/preferences/BasePreferenceFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/preferences/BasePreferenceFragment.java
index 1a54bff9a..71892a537 100755
--- a/app/src/main/java/com/itsaky/androidide/fragments/preferences/BasePreferenceFragment.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/preferences/BasePreferenceFragment.java
@@ -31,6 +31,11 @@ import com.itsaky.androidide.managers.PreferenceManager;
public abstract class BasePreferenceFragment extends PreferenceFragmentCompat {
+ @Override
+ public void onCreatePreferences(Bundle p1, String p2) {
+ setPreferencesFromResource(com.itsaky.androidide.R.xml.ide_prefs, p2);
+ }
+
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -43,11 +48,6 @@ public abstract class BasePreferenceFragment extends PreferenceFragmentCompat {
return v;
}
- @Override
- public void onCreatePreferences(Bundle p1, String p2) {
- setPreferencesFromResource(com.itsaky.androidide.R.xml.ide_prefs, p2);
- }
-
protected PreferenceManager getPrefManager() {
return StudioApp.getInstance().getPrefManager();
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/preferences/BuildPreferences.java b/app/src/main/java/com/itsaky/androidide/fragments/preferences/BuildPreferences.java
index 466a76bc9..f4961b57f 100755
--- a/app/src/main/java/com/itsaky/androidide/fragments/preferences/BuildPreferences.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/preferences/BuildPreferences.java
@@ -120,15 +120,6 @@ public class BuildPreferences extends BasePreferenceFragment
return true;
}
- @Override
- public boolean onPreferenceChange(final Preference preference, final Object newValue) {
- final var key = preference.getKey();
- if (KEY_TP_FIX.equals(key)) {
- getPrefManager().putBoolean(KEY_TP_FIX, ((boolean) newValue));
- }
- return true;
- }
-
private void changeGradleDist() {
final var builder = DialogUtils.newMaterialDialogBuilder(getContext());
final var binding = LayoutDialogTextInputBinding.inflate(getLayoutInflater());
@@ -228,4 +219,13 @@ public class BuildPreferences extends BasePreferenceFragment
? progressSheet = new ProgressSheet().setMessage(getString(R.string.please_wait))
: progressSheet;
}
+
+ @Override
+ public boolean onPreferenceChange(final Preference preference, final Object newValue) {
+ final var key = preference.getKey();
+ if (KEY_TP_FIX.equals(key)) {
+ getPrefManager().putBoolean(KEY_TP_FIX, ((boolean) newValue));
+ }
+ return true;
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/preferences/IDEPreferences.java b/app/src/main/java/com/itsaky/androidide/fragments/preferences/IDEPreferences.java
index 15dcba6d9..f4e3cee23 100755
--- a/app/src/main/java/com/itsaky/androidide/fragments/preferences/IDEPreferences.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/preferences/IDEPreferences.java
@@ -123,20 +123,6 @@ public class IDEPreferences extends BasePreferenceFragment
: mBuildPreferences;
}
- private void showChangelog() {
- final var intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(
- Uri.parse(
- BaseApplication.GITHUB_URL.concat("/releases/tag/v").concat(BuildConfig.VERSION_NAME)));
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- startActivity(intent);
- } catch (Throwable th) {
- LOG.error("Unable to start activity to show changelog", th);
- StudioApp.getInstance().toast("Unable to start activity", Toaster.Type.ERROR);
- }
- }
-
@Override
public boolean onPreferenceClick(@NonNull Preference preference) {
final String key = preference.getKey();
@@ -156,4 +142,18 @@ public class IDEPreferences extends BasePreferenceFragment
}
return true;
}
+
+ private void showChangelog() {
+ final var intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(
+ Uri.parse(
+ BaseApplication.GITHUB_URL.concat("/releases/tag/v").concat(BuildConfig.VERSION_NAME)));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ startActivity(intent);
+ } catch (Throwable th) {
+ LOG.error("Unable to start activity to show changelog", th);
+ StudioApp.getInstance().toast("Unable to start activity", Toaster.Type.ERROR);
+ }
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttrEditorSheet.java b/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttrEditorSheet.java
index 0a01e99d1..6ce903dc2 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttrEditorSheet.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttrEditorSheet.java
@@ -102,19 +102,6 @@ public class AttrEditorSheet extends BottomSheetDialogFragment
setupViewData();
}
- @Override
- public void onAttach(@NonNull Context context) {
- super.onAttach(context);
- mDeletionFailedListener = (OnViewDeletionFailedListener) context;
- }
-
- public AttrEditorSheet setLayout(File layout) {
- Objects.requireNonNull(layout);
-
- this.layout = layout;
- return this;
- }
-
private void setupViewData() {
binding.actionsList.setAdapter(new SimpleIconTextAdapter(VIEW_ACTIONS).setOnBindListener(this));
@@ -132,10 +119,6 @@ public class AttrEditorSheet extends BottomSheetDialogFragment
this::onAttrClick));
}
- public void setSelectedView(IView view) {
- this.selectedView = view;
- }
-
private void onAttrClick(
LayoutAttrEditorSheetItemBinding binding, @NonNull XMLAttribute attribute) {
@@ -158,6 +141,42 @@ public class AttrEditorSheet extends BottomSheetDialogFragment
getValueEditorSheet(attribute).show(getChildFragmentManager(), "attr_value_editor_sheet");
}
+ @NonNull
+ public AttrValueEditorSheet getValueEditorSheet(@NonNull XMLAttribute attribute) {
+
+ if (mValueEditorSheet == null) {
+ mValueEditorSheet = AttrValueEditorSheet.newInstance(attribute);
+ }
+
+ mValueEditorSheet.setAttribute(attribute);
+ return mValueEditorSheet;
+ }
+
+ private boolean dismissIfSelectedNull() {
+ if (selectedView == null) {
+ dismiss();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onAttach(@NonNull Context context) {
+ super.onAttach(context);
+ mDeletionFailedListener = (OnViewDeletionFailedListener) context;
+ }
+
+ public AttrEditorSheet setLayout(File layout) {
+ Objects.requireNonNull(layout);
+
+ this.layout = layout;
+ return this;
+ }
+
+ public void setSelectedView(IView view) {
+ this.selectedView = view;
+ }
+
@Override
public void postBind(
IconTextListItem item, @NonNull SimpleIconTextAdapter.VH holder, int position) {
@@ -276,11 +295,6 @@ public class AttrEditorSheet extends BottomSheetDialogFragment
return new ArrayList<>(attributes);
}
- @Override
- public void accept(Attr attr) {
- addNewAttribute(attr);
- }
-
@NonNull
private AttributeListSheet getAttrListSheet() {
if (mAttrListSheet == null) {
@@ -291,15 +305,15 @@ public class AttrEditorSheet extends BottomSheetDialogFragment
return mAttrListSheet;
}
- @NonNull
- public AttrValueEditorSheet getValueEditorSheet(@NonNull XMLAttribute attribute) {
+ @Override
+ public void accept(Attr attr) {
+ addNewAttribute(attr);
+ }
- if (mValueEditorSheet == null) {
- mValueEditorSheet = AttrValueEditorSheet.newInstance(attribute);
- }
-
- mValueEditorSheet.setAttribute(attribute);
- return mValueEditorSheet;
+ private void addNewAttribute(@NonNull Attr attr) {
+ final XMLAttribute attribute = new XMLAttribute(attr.namespace, attr.name, "", false);
+ attribute.setAttr(attr);
+ showValueEditorSheet(attribute);
}
@Override
@@ -320,20 +334,6 @@ public class AttrEditorSheet extends BottomSheetDialogFragment
}
}
- private void addNewAttribute(@NonNull Attr attr) {
- final XMLAttribute attribute = new XMLAttribute(attr.namespace, attr.name, "", false);
- attribute.setAttr(attr);
- showValueEditorSheet(attribute);
- }
-
- private boolean dismissIfSelectedNull() {
- if (selectedView == null) {
- dismiss();
- return true;
- }
- return false;
- }
-
/**
* A listener can be used to get notified when we fail to remove a view from its parent. This is
* used in {@link com.itsaky.androidide.DesignerActivity DesignerActivity}.
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttributeListSheet.java b/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttributeListSheet.java
index 0a01a1981..a4a5ea473 100644
--- a/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttributeListSheet.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/sheets/AttributeListSheet.java
@@ -53,12 +53,6 @@ public class AttributeListSheet extends BottomSheetDialogFragment {
private Consumer clickConsumer;
private List mItems;
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setStyle(DialogFragment.STYLE_NORMAL, R.style.AppTheme_SheetAboveKeyboard);
- }
-
@Nullable
@Override
public View onCreateView(
@@ -104,6 +98,16 @@ public class AttributeListSheet extends BottomSheetDialogFragment {
return true;
}
+ public void update() {
+ update(mItems);
+ }
+
+ public void update(List items) {
+ if (binding != null) {
+ binding.attrList.setAdapter(new AttrListAdapter(clickConsumer, items));
+ }
+ }
+
public void setItems(@Nullable List items) {
if (items == null) {
items = new ArrayList<>();
@@ -120,13 +124,9 @@ public class AttributeListSheet extends BottomSheetDialogFragment {
this.clickConsumer = (Consumer) getParentFragment();
}
- public void update() {
- update(mItems);
- }
-
- public void update(List items) {
- if (binding != null) {
- binding.attrList.setAdapter(new AttrListAdapter(clickConsumer, items));
- }
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setStyle(DialogFragment.STYLE_NORMAL, R.style.AppTheme_SheetAboveKeyboard);
}
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/sheets/BaseBottomSheetFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/sheets/BaseBottomSheetFragment.java
index 31b5be043..e2a5396cd 100755
--- a/app/src/main/java/com/itsaky/androidide/fragments/sheets/BaseBottomSheetFragment.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/sheets/BaseBottomSheetFragment.java
@@ -47,6 +47,8 @@ public abstract class BaseBottomSheetFragment extends BottomSheetDialogFragment
return mDialog;
}
+ protected void onShow() {}
+
@Override
public View onCreateView(
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -97,10 +99,6 @@ public abstract class BaseBottomSheetFragment extends BottomSheetDialogFragment
}
}
- public boolean isShowing() {
- return mDialog != null && mDialog.isShowing();
- }
-
protected boolean shouldHideTitle() {
return !titleEnabled;
}
@@ -123,6 +121,12 @@ public abstract class BaseBottomSheetFragment extends BottomSheetDialogFragment
return this;
}
+ protected abstract void bind(LinearLayout container);
+
+ public boolean isShowing() {
+ return mDialog != null && mDialog.isShowing();
+ }
+
public void setShowShadow(boolean enabled) {
this.shadowEnabled = enabled;
}
@@ -131,10 +135,6 @@ public abstract class BaseBottomSheetFragment extends BottomSheetDialogFragment
this.titleEnabled = enabled;
}
- protected void onShow() {}
-
- protected abstract void bind(LinearLayout container);
-
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/sheets/OptionsListFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/sheets/OptionsListFragment.java
index 0de6aa74c..3893a2608 100755
--- a/app/src/main/java/com/itsaky/androidide/fragments/sheets/OptionsListFragment.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/sheets/OptionsListFragment.java
@@ -42,13 +42,6 @@ public class OptionsListFragment extends BaseBottomSheetFragment {
private RecyclerView mList;
private OnOptionsClickListener listener;
- @Override
- protected void bind(@NonNull LinearLayout container) {
- mList = new RecyclerView(requireContext());
- container.removeAllViews();
- container.addView(mList, new LinearLayout.LayoutParams(-1, -1));
- }
-
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@@ -64,6 +57,18 @@ public class OptionsListFragment extends BaseBottomSheetFragment {
}));
}
+ @Override
+ protected String getTitle() {
+ return getString(com.itsaky.androidide.R.string.file_options);
+ }
+
+ @Override
+ protected void bind(@NonNull LinearLayout container) {
+ mList = new RecyclerView(requireContext());
+ container.removeAllViews();
+ container.addView(mList, new LinearLayout.LayoutParams(-1, -1));
+ }
+
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
@@ -90,11 +95,6 @@ public class OptionsListFragment extends BaseBottomSheetFragment {
return this;
}
- @Override
- protected String getTitle() {
- return getString(com.itsaky.androidide.R.string.file_options);
- }
-
public static interface OnOptionsClickListener {
void onOptionsClick(SheetOption option);
}
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/sheets/ProgressSheet.java b/app/src/main/java/com/itsaky/androidide/fragments/sheets/ProgressSheet.java
index c0deb4d9a..917b4f017 100755
--- a/app/src/main/java/com/itsaky/androidide/fragments/sheets/ProgressSheet.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/sheets/ProgressSheet.java
@@ -41,12 +41,6 @@ public class ProgressSheet extends BaseBottomSheetFragment {
private boolean subMessageEnabled = false;
private boolean welcomeTextEnabled = false;
- @Override
- protected void bind(LinearLayout container) {
- binding = LayoutProgressSheetBinding.inflate(LayoutInflater.from(getContext()));
- container.addView(binding.getRoot());
- }
-
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@@ -85,6 +79,12 @@ public class ProgressSheet extends BaseBottomSheetFragment {
return true;
}
+ @Override
+ protected void bind(LinearLayout container) {
+ binding = LayoutProgressSheetBinding.inflate(LayoutInflater.from(getContext()));
+ container.addView(binding.getRoot());
+ }
+
public ProgressSheet setWelcomeTextEnabled(boolean enabled) {
this.welcomeTextEnabled = enabled;
return this;
diff --git a/app/src/main/java/com/itsaky/androidide/fragments/sheets/TextSheetFragment.java b/app/src/main/java/com/itsaky/androidide/fragments/sheets/TextSheetFragment.java
index dffd7ccd8..1144a8d88 100755
--- a/app/src/main/java/com/itsaky/androidide/fragments/sheets/TextSheetFragment.java
+++ b/app/src/main/java/com/itsaky/androidide/fragments/sheets/TextSheetFragment.java
@@ -40,34 +40,6 @@ public class TextSheetFragment extends BaseBottomSheetFragment {
return this;
}
- @Override
- protected void bind(@NonNull LinearLayout container) {
- final IDEEditor e = getEditor();
- container.setPadding(0, 0, 0, 0);
- container.setPaddingRelative(0, 0, 0, 0);
- LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(-1, 0);
- p.weight = 1.0f;
- if (e.getParent() != null && e.getParent() instanceof ViewGroup) {
- ((ViewGroup) e.getParent()).removeView(e);
- }
- container.addView(getEditor(), p);
- }
-
- @Override
- protected String getTitle() {
- return getString(R.string.build_output);
- }
-
- @Override
- protected void onShow() {
- super.onShow();
- editor.setText(getOutputBuilder());
- }
-
- private void scrollToBottom() {
- if (getActivity() != null) getActivity().runOnUiThread(() -> editor.goToEnd());
- }
-
public TextSheetFragment setTitleText(int res) {
super.setTitle(res);
return this;
@@ -111,6 +83,34 @@ public class TextSheetFragment extends BaseBottomSheetFragment {
});
}
+ private void scrollToBottom() {
+ if (getActivity() != null) getActivity().runOnUiThread(() -> editor.goToEnd());
+ }
+
+ @Override
+ protected String getTitle() {
+ return getString(R.string.build_output);
+ }
+
+ @Override
+ protected void onShow() {
+ super.onShow();
+ editor.setText(getOutputBuilder());
+ }
+
+ @Override
+ protected void bind(@NonNull LinearLayout container) {
+ final IDEEditor e = getEditor();
+ container.setPadding(0, 0, 0, 0);
+ container.setPaddingRelative(0, 0, 0, 0);
+ LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(-1, 0);
+ p.weight = 1.0f;
+ if (e.getParent() != null && e.getParent() instanceof ViewGroup) {
+ ((ViewGroup) e.getParent()).removeView(e);
+ }
+ container.addView(getEditor(), p);
+ }
+
private IDEEditor getEditor() {
return editor == null ? createEditor() : editor;
}
diff --git a/app/src/main/java/com/itsaky/androidide/language/IDELanguage.java b/app/src/main/java/com/itsaky/androidide/language/IDELanguage.java
index 15d318aaa..3c407446c 100644
--- a/app/src/main/java/com/itsaky/androidide/language/IDELanguage.java
+++ b/app/src/main/java/com/itsaky/androidide/language/IDELanguage.java
@@ -20,11 +20,6 @@ import androidx.annotation.NonNull;
import com.itsaky.androidide.app.StudioApp;
import com.itsaky.lsp.api.ILanguageServer;
-import com.itsaky.lsp.models.DiagnosticItem;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
import io.github.rosemoe.sora.lang.Language;
@@ -40,10 +35,6 @@ public abstract class IDELanguage implements Language {
return false;
}
- public int getTabSize() {
- return StudioApp.getInstance().getPrefManager().getEditorTabSize();
- }
-
@Override
public CharSequence format(CharSequence text) {
final var server = getLanguageServer();
@@ -54,11 +45,15 @@ public abstract class IDELanguage implements Language {
return text;
}
- public int getIndentAdvance(@NonNull String line) {
- return 0;
- }
-
protected ILanguageServer getLanguageServer() {
return null;
}
+
+ public int getTabSize() {
+ return StudioApp.getInstance().getPrefManager().getEditorTabSize();
+ }
+
+ public int getIndentAdvance(@NonNull String line) {
+ return 0;
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/language/cpp/CppAnalyzer.java b/app/src/main/java/com/itsaky/androidide/language/cpp/CppAnalyzer.java
index 2a7505be1..836265993 100644
--- a/app/src/main/java/com/itsaky/androidide/language/cpp/CppAnalyzer.java
+++ b/app/src/main/java/com/itsaky/androidide/language/cpp/CppAnalyzer.java
@@ -26,13 +26,9 @@ import com.itsaky.androidide.utils.ILogger;
import java.lang.Override;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
-import io.github.rosemoe.sora.lang.analysis.AsyncIncrementalAnalyzeManager;
-import io.github.rosemoe.sora.lang.styling.CodeBlock;
import io.github.rosemoe.sora.lang.styling.Span;
-import io.github.rosemoe.sora.text.Content;
public class CppAnalyzer extends BaseIncrementalAnalyzeManager {
@@ -43,8 +39,10 @@ public class CppAnalyzer extends BaseIncrementalAnalyzeManager {
}
@Override
- protected int[] getCodeBlockTokens() {
- return new int[] {LeftBrace, RightBrace};
+ protected int[][] getMultilineTokenStartEndTypes() {
+ final var start = new int[] {Div, Star};
+ final var end = new int[] {Star, Div};
+ return new int[][] {start, end};
}
@Override
@@ -215,15 +213,13 @@ public class CppAnalyzer extends BaseIncrementalAnalyzeManager {
return spans;
}
- @Override
- protected int[][] getMultilineTokenStartEndTypes() {
- final var start = new int[] {Div, Star};
- final var end = new int[] {Star, Div};
- return new int[][] {start, end};
- }
-
@Override
protected void handleIncompleteToken(final IncrementalToken token) {
token.type = BlockComment;
}
+
+ @Override
+ protected int[] getCodeBlockTokens() {
+ return new int[] {LeftBrace, RightBrace};
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/language/cpp/CppLanguage.java b/app/src/main/java/com/itsaky/androidide/language/cpp/CppLanguage.java
index a51801cb1..7809b3002 100644
--- a/app/src/main/java/com/itsaky/androidide/language/cpp/CppLanguage.java
+++ b/app/src/main/java/com/itsaky/androidide/language/cpp/CppLanguage.java
@@ -43,42 +43,13 @@ import io.github.rosemoe.sora.widget.SymbolPairMatch;
public class CppLanguage extends IDELanguage {
private static final ILogger LOG = ILogger.newInstance("CppLanguage");
- private CppAnalyzer analyzer;
private final NewlineHandler[] newlineHandlers = new NewlineHandler[] {new BraceHandler()};
+ private CppAnalyzer analyzer;
public CppLanguage() {
analyzer = new CppAnalyzer();
}
- @Override
- public int getIndentAdvance(@NonNull String line) {
- try {
- CPP14Lexer lexer = new CPP14Lexer(CharStreams.fromReader(new StringReader(line)));
- Token token;
- int advance = 0;
- while (((token = lexer.nextToken()) != null && token.getType() != token.EOF)) {
- switch (token.getType()) {
- case CPP14Lexer.LeftBrace:
- advance++;
- break;
- case CPP14Lexer.RightBrace:
- advance--;
- break;
- }
- }
- advance = Math.max(0, advance);
- return advance * getTabSize();
- } catch (Throwable e) {
- LOG.error("Error calculating indent advance", e);
- }
- return 0;
- }
-
- @Override
- public SymbolPairMatch getSymbolPairs() {
- return new CppSymbolPairs();
- }
-
@NonNull
@Override
public AnalyzeManager getAnalyzeManager() {
@@ -107,8 +78,8 @@ public class CppLanguage extends IDELanguage {
}
@Override
- public CharSequence format(CharSequence content) {
- return content;
+ public SymbolPairMatch getSymbolPairs() {
+ return new CppSymbolPairs();
}
@Override
@@ -121,6 +92,35 @@ public class CppLanguage extends IDELanguage {
analyzer = null;
}
+ @Override
+ public CharSequence format(CharSequence content) {
+ return content;
+ }
+
+ @Override
+ public int getIndentAdvance(@NonNull String line) {
+ try {
+ CPP14Lexer lexer = new CPP14Lexer(CharStreams.fromReader(new StringReader(line)));
+ Token token;
+ int advance = 0;
+ while (((token = lexer.nextToken()) != null && token.getType() != token.EOF)) {
+ switch (token.getType()) {
+ case CPP14Lexer.LeftBrace:
+ advance++;
+ break;
+ case CPP14Lexer.RightBrace:
+ advance--;
+ break;
+ }
+ }
+ advance = Math.max(0, advance);
+ return advance * getTabSize();
+ } catch (Throwable e) {
+ LOG.error("Error calculating indent advance", e);
+ }
+ return 0;
+ }
+
private static class CppSymbolPairs extends SymbolPairMatch {
public CppSymbolPairs() {
super.putPair('{', new Replacement("{}", 1));
diff --git a/app/src/main/java/com/itsaky/androidide/language/groovy/GroovyAnalyzer.kt b/app/src/main/java/com/itsaky/androidide/language/groovy/GroovyAnalyzer.kt
index 6b7a1a351..f310976d4 100644
--- a/app/src/main/java/com/itsaky/androidide/language/groovy/GroovyAnalyzer.kt
+++ b/app/src/main/java/com/itsaky/androidide/language/groovy/GroovyAnalyzer.kt
@@ -23,10 +23,8 @@ import com.itsaky.androidide.language.incremental.LineState
import com.itsaky.androidide.lexers.groovy.GroovyLexer
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE
import io.github.rosemoe.sora.lang.analysis.IncrementalAnalyzeManager.LineTokenizeResult
-import io.github.rosemoe.sora.lang.styling.CodeBlock
import io.github.rosemoe.sora.lang.styling.Span
import io.github.rosemoe.sora.lang.styling.TextStyle
-import io.github.rosemoe.sora.text.Content
/** @author Akash Yadav */
class GroovyAnalyzer : BaseIncrementalAnalyzeManager(GroovyLexer::class.java) {
diff --git a/app/src/main/java/com/itsaky/androidide/language/groovy/GroovyLanguage.java b/app/src/main/java/com/itsaky/androidide/language/groovy/GroovyLanguage.java
index 1f92ae3f4..d73a23993 100755
--- a/app/src/main/java/com/itsaky/androidide/language/groovy/GroovyLanguage.java
+++ b/app/src/main/java/com/itsaky/androidide/language/groovy/GroovyLanguage.java
@@ -53,35 +53,6 @@ public class GroovyLanguage extends IDELanguage {
completer = new GroovyAutoComplete();
}
- @Override
- public int getIndentAdvance(@NonNull String p1) {
- try {
- GroovyLexer lexer = new GroovyLexer(CharStreams.fromReader(new StringReader(p1)));
- Token token = null;
- int advance = 0;
- while (((token = lexer.nextToken()) != null && token.getType() != token.EOF)) {
- switch (token.getType()) {
- case GroovyLexer.LBRACE:
- advance++;
- break;
- case GroovyLexer.RBRACE:
- advance--;
- break;
- }
- }
- advance = Math.max(0, advance);
- return advance * getTabSize();
- } catch (Throwable e) {
- LOG.error("Failed to calculate indent advance", e);
- }
- return 0;
- }
-
- @Override
- public SymbolPairMatch getSymbolPairs() {
- return new SymbolPairMatch.DefaultSymbolPairs();
- }
-
@NonNull
@Override
public AnalyzeManager getAnalyzeManager() {
@@ -129,8 +100,8 @@ public class GroovyLanguage extends IDELanguage {
}
@Override
- public CharSequence format(CharSequence content) {
- return content;
+ public SymbolPairMatch getSymbolPairs() {
+ return new SymbolPairMatch.DefaultSymbolPairs();
}
@Override
@@ -141,6 +112,35 @@ public class GroovyLanguage extends IDELanguage {
@Override
public void destroy() {}
+ @Override
+ public CharSequence format(CharSequence content) {
+ return content;
+ }
+
+ @Override
+ public int getIndentAdvance(@NonNull String p1) {
+ try {
+ GroovyLexer lexer = new GroovyLexer(CharStreams.fromReader(new StringReader(p1)));
+ Token token = null;
+ int advance = 0;
+ while (((token = lexer.nextToken()) != null && token.getType() != token.EOF)) {
+ switch (token.getType()) {
+ case GroovyLexer.LBRACE:
+ advance++;
+ break;
+ case GroovyLexer.RBRACE:
+ advance--;
+ break;
+ }
+ }
+ advance = Math.max(0, advance);
+ return advance * getTabSize();
+ } catch (Throwable e) {
+ LOG.error("Failed to calculate indent advance", e);
+ }
+ return 0;
+ }
+
class BraceHandler implements NewlineHandler {
@Override
diff --git a/app/src/main/java/com/itsaky/androidide/language/incremental/BaseIncrementalAnalyzeManager.java b/app/src/main/java/com/itsaky/androidide/language/incremental/BaseIncrementalAnalyzeManager.java
index bcf630e1d..f1c0eec0c 100644
--- a/app/src/main/java/com/itsaky/androidide/language/incremental/BaseIncrementalAnalyzeManager.java
+++ b/app/src/main/java/com/itsaky/androidide/language/incremental/BaseIncrementalAnalyzeManager.java
@@ -61,11 +61,11 @@ import kotlin.Pair;
public abstract class BaseIncrementalAnalyzeManager
extends AsyncIncrementalAnalyzeManager {
+ private static final ILogger LOG = ILogger.newInstance("BaseIncrementalAnalyzeManager");
protected final Lexer lexer;
private final int[] multilineStartTypes;
private final int[] multilineEndTypes;
private final int[] blockTokens;
- private static final ILogger LOG = ILogger.newInstance("BaseIncrementalAnalyzeManager");
public BaseIncrementalAnalyzeManager(final Class extends Lexer> lexer) {
Objects.requireNonNull(lexer, "Cannot create analyzer manager for null lexer");
@@ -92,6 +92,16 @@ public abstract class BaseIncrementalAnalyzeManager
}
}
+ @NonNull
+ protected CharStream createStream(@NonNull CharSequence source) {
+ Objects.requireNonNull(source);
+ try {
+ return CharStreams.fromReader(new CharSequenceReader(source));
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot create CharStream for source", e);
+ }
+ }
+
private void verifyMultilineTypes(@NonNull final int[][] types) {
Preconditions.checkState(
types.length == 2, "There must be exact two inner int[] in multiline token types");
@@ -102,45 +112,6 @@ public abstract class BaseIncrementalAnalyzeManager
Preconditions.checkState(end.length > 0, "Invalid end token types");
}
- @SuppressWarnings("UnstableApiUsage")
- @NonNull
- private Pair, EvictingQueue>
- createEvictingQueueForTokens() {
- return new Pair<>(
- EvictingQueue.create(multilineStartTypes.length),
- EvictingQueue.create(multilineEndTypes.length));
- }
-
- @SuppressWarnings("UnstableApiUsage")
- protected boolean isIncompleteTokenStart(EvictingQueue q) {
- return matchTokenTypes(this.multilineStartTypes, q);
- }
-
- @SuppressWarnings("UnstableApiUsage")
- protected boolean isIncompleteTokenEnd(EvictingQueue q) {
- return matchTokenTypes(this.multilineEndTypes, q);
- }
-
- @SuppressWarnings("UnstableApiUsage")
- private boolean matchTokenTypes(
- @NonNull int[] types, @NonNull EvictingQueue tokens) {
- final var arr = tokens.toArray(new IncrementalToken[0]);
- for (int i = 0; i < types.length; i++) {
- if (types[i] != arr[i].getType()) {
- return false;
- }
- }
- return true;
- }
-
- protected boolean isCodeBlockStart(IncrementalToken token) {
- return blockTokens.length == 2 && token.getType() == blockTokens[0];
- }
-
- protected boolean isCodeBlockEnd(IncrementalToken token) {
- return blockTokens.length == 2 && token.getType() == blockTokens[1];
- }
-
/**
* Returns the token types which start and end a multiline token.
*
@@ -152,31 +123,6 @@ public abstract class BaseIncrementalAnalyzeManager
*/
protected abstract int[][] getMultilineTokenStartEndTypes();
- /**
- * Generate spans for the given {@link LineTokenizeResult}.
- *
- * @param tokens The tokenization result.
- * @return The spans for the tokens.
- */
- protected abstract List generateSpans(
- final LineTokenizeResult tokens);
-
- /**
- * Called when the analyzer finds an incomplete token in a lne.
- *
- * @param token The incomplete token.
- */
- protected abstract void handleIncompleteToken(IncrementalToken token);
-
- /**
- * Gets the next token from lexer and return an {@link IncrementalToken}.
- *
- * @return The next {@link IncrementalToken}.
- */
- protected IncrementalToken nextToken() {
- return new IncrementalToken(lexer.nextToken());
- }
-
/**
* Get the token types for left and right braces.
*
@@ -184,51 +130,6 @@ public abstract class BaseIncrementalAnalyzeManager
*/
protected abstract int[] getCodeBlockTokens();
- /**
- * Pop (remove) required number of tokens after an incomplete token has been encountered.
- *
- * For example:
- * When ['/', '*'] tokens are encountered, the '*' token must be removed. In this case,
- * incompleteToken parameter will point to '/' token.
- *
- *
By default, this method removes only the last token.
- *
- * @param incompleteToken The token which is the start of the incomplete token.
- * @param tokens The list of tokens from which extra tokens must be removed.
- */
- protected void popTokensAfterIncomplete(
- @NonNull IncrementalToken incompleteToken, @NonNull List tokens) {
- tokens.remove(tokens.size() - 1);
- }
-
- @NonNull
- protected CharStream createStream(@NonNull CharSequence source) {
- Objects.requireNonNull(source);
- try {
- return CharStreams.fromReader(new CharSequenceReader(source));
- } catch (IOException e) {
- throw new RuntimeException("Cannot create CharStream for source", e);
- }
- }
-
- protected void handleLineCommentSpan(
- @NonNull IncrementalToken token, @NonNull List spans, int offset) {
- var commentType = SchemeAndroidIDE.COMMENT;
-
- // highlight special line comments
- var commentText = token.getText();
- if (commentText.length() > 2) {
- commentText = commentText.substring(2);
- commentText = commentText.trim();
- if ("todo".equalsIgnoreCase(commentText.substring(0, 4))) {
- commentType = TODO_COMMENT;
- } else if ("fixme".equalsIgnoreCase(commentText.substring(0, 5))) {
- commentType = FIXME_COMMENT;
- }
- }
- spans.add(Span.obtain(offset, withoutCompletion(commentType)));
- }
-
@Override
public LineState getInitialState() {
return new LineState();
@@ -239,6 +140,52 @@ public abstract class BaseIncrementalAnalyzeManager
return state.equals(another);
}
+ @Override
+ public LineTokenizeResult tokenizeLine(
+ final CharSequence line, final LineState state) {
+ final var tokens = new ArrayList();
+ var newState = 0;
+ var stateObj = new LineState();
+ if (state.state == NORMAL) {
+ newState = tokenizeNormal(line, 0, tokens, stateObj, state.lexerMode);
+ } else if (state.state == INCOMPLETE) {
+ final var result = fillIncomplete(line, tokens, state.lexerMode);
+ newState = IntPair.getFirst(result);
+ if (newState == NORMAL) {
+ newState =
+ tokenizeNormal(line, IntPair.getSecond(result), tokens, stateObj, state.lexerMode);
+ } else {
+ newState = INCOMPLETE;
+ }
+ }
+ stateObj.state = newState;
+ stateObj.lexerMode = lexer._mode;
+ return new LineTokenizeResult<>(stateObj, tokens);
+ }
+
+ @Override
+ public List generateSpansForLine(
+ final LineTokenizeResult tokens) {
+ var result = generateSpans(tokens);
+
+ Objects.requireNonNull(result);
+
+ if (result.isEmpty()) {
+ result.add(Span.obtain(0, TextStyle.makeStyle(SchemeAndroidIDE.TEXT_NORMAL)));
+ }
+
+ return result;
+ }
+
+ /**
+ * Generate spans for the given {@link LineTokenizeResult}.
+ *
+ * @param tokens The tokenization result.
+ * @return The spans for the tokens.
+ */
+ protected abstract List generateSpans(
+ final LineTokenizeResult tokens);
+
@Override
public List computeBlocks(
final Content text,
@@ -292,27 +239,73 @@ public abstract class BaseIncrementalAnalyzeManager
return blocks;
}
- @Override
- public LineTokenizeResult tokenizeLine(
- final CharSequence line, final LineState state) {
- final var tokens = new ArrayList();
- var newState = 0;
- var stateObj = new LineState();
- if (state.state == NORMAL) {
- newState = tokenizeNormal(line, 0, tokens, stateObj, state.lexerMode);
- } else if (state.state == INCOMPLETE) {
- final var result = fillIncomplete(line, tokens, state.lexerMode);
- newState = IntPair.getFirst(result);
- if (newState == NORMAL) {
- newState =
- tokenizeNormal(line, IntPair.getSecond(result), tokens, stateObj, state.lexerMode);
- } else {
- newState = INCOMPLETE;
+ protected boolean isCodeBlockStart(IncrementalToken token) {
+ return blockTokens.length == 2 && token.getType() == blockTokens[0];
+ }
+
+ protected boolean isCodeBlockEnd(IncrementalToken token) {
+ return blockTokens.length == 2 && token.getType() == blockTokens[1];
+ }
+
+ @SuppressWarnings("UnstableApiUsage")
+ protected boolean isIncompleteTokenStart(EvictingQueue q) {
+ return matchTokenTypes(this.multilineStartTypes, q);
+ }
+
+ @SuppressWarnings("UnstableApiUsage")
+ protected boolean isIncompleteTokenEnd(EvictingQueue q) {
+ return matchTokenTypes(this.multilineEndTypes, q);
+ }
+
+ /**
+ * Called when the analyzer finds an incomplete token in a lne.
+ *
+ * @param token The incomplete token.
+ */
+ protected abstract void handleIncompleteToken(IncrementalToken token);
+
+ /**
+ * Gets the next token from lexer and return an {@link IncrementalToken}.
+ *
+ * @return The next {@link IncrementalToken}.
+ */
+ protected IncrementalToken nextToken() {
+ return new IncrementalToken(lexer.nextToken());
+ }
+
+ /**
+ * Pop (remove) required number of tokens after an incomplete token has been encountered.
+ *
+ * For example:
+ * When ['/', '*'] tokens are encountered, the '*' token must be removed. In this case,
+ * incompleteToken parameter will point to '/' token.
+ *
+ *
By default, this method removes only the last token.
+ *
+ * @param incompleteToken The token which is the start of the incomplete token.
+ * @param tokens The list of tokens from which extra tokens must be removed.
+ */
+ protected void popTokensAfterIncomplete(
+ @NonNull IncrementalToken incompleteToken, @NonNull List tokens) {
+ tokens.remove(tokens.size() - 1);
+ }
+
+ protected void handleLineCommentSpan(
+ @NonNull IncrementalToken token, @NonNull List spans, int offset) {
+ var commentType = SchemeAndroidIDE.COMMENT;
+
+ // highlight special line comments
+ var commentText = token.getText();
+ if (commentText.length() > 2) {
+ commentText = commentText.substring(2);
+ commentText = commentText.trim();
+ if ("todo".equalsIgnoreCase(commentText.substring(0, 4))) {
+ commentType = TODO_COMMENT;
+ } else if ("fixme".equalsIgnoreCase(commentText.substring(0, 5))) {
+ commentType = FIXME_COMMENT;
}
}
- stateObj.state = newState;
- stateObj.lexerMode = lexer._mode;
- return new LineTokenizeResult<>(stateObj, tokens);
+ spans.add(Span.obtain(offset, withoutCompletion(commentType)));
}
/**
@@ -445,17 +438,24 @@ public abstract class BaseIncrementalAnalyzeManager
}
}
- @Override
- public List generateSpansForLine(
- final LineTokenizeResult tokens) {
- var result = generateSpans(tokens);
+ @SuppressWarnings("UnstableApiUsage")
+ @NonNull
+ private Pair, EvictingQueue>
+ createEvictingQueueForTokens() {
+ return new Pair<>(
+ EvictingQueue.create(multilineStartTypes.length),
+ EvictingQueue.create(multilineEndTypes.length));
+ }
- Objects.requireNonNull(result);
-
- if (result.isEmpty()) {
- result.add(Span.obtain(0, TextStyle.makeStyle(SchemeAndroidIDE.TEXT_NORMAL)));
+ @SuppressWarnings("UnstableApiUsage")
+ private boolean matchTokenTypes(
+ @NonNull int[] types, @NonNull EvictingQueue tokens) {
+ final var arr = tokens.toArray(new IncrementalToken[0]);
+ for (int i = 0; i < types.length; i++) {
+ if (types[i] != arr[i].getType()) {
+ return false;
+ }
}
-
- return result;
+ return true;
}
}
diff --git a/app/src/main/java/com/itsaky/androidide/language/java/JavaAnalyzer.kt b/app/src/main/java/com/itsaky/androidide/language/java/JavaAnalyzer.kt
index ccf956453..aa6654102 100644
--- a/app/src/main/java/com/itsaky/androidide/language/java/JavaAnalyzer.kt
+++ b/app/src/main/java/com/itsaky/androidide/language/java/JavaAnalyzer.kt
@@ -30,10 +30,8 @@ import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.forKeyword
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.forString
import com.itsaky.androidide.utils.ILogger
import io.github.rosemoe.sora.lang.analysis.IncrementalAnalyzeManager.LineTokenizeResult
-import io.github.rosemoe.sora.lang.styling.CodeBlock
import io.github.rosemoe.sora.lang.styling.Span
import io.github.rosemoe.sora.lang.styling.TextStyle.makeStyle
-import io.github.rosemoe.sora.text.Content
/** @author Akash Yadav */
class JavaAnalyzer : BaseIncrementalAnalyzeManager(JavaLexer::class.java) {
diff --git a/app/src/main/java/com/itsaky/androidide/language/java/JavaLanguage.java b/app/src/main/java/com/itsaky/androidide/language/java/JavaLanguage.java
index 0be2c0060..c62817c2c 100755
--- a/app/src/main/java/com/itsaky/androidide/language/java/JavaLanguage.java
+++ b/app/src/main/java/com/itsaky/androidide/language/java/JavaLanguage.java
@@ -63,36 +63,6 @@ public class JavaLanguage extends IDELanguage {
this.newlineHandlers[0] = new BraceHandler();
}
- @Override
- public int getIndentAdvance(@NonNull String line) {
- try {
- JavaLexer lexer = new JavaLexer(CharStreams.fromReader(new StringReader(line)));
- Token token;
- int advance = 0;
- while (((token = lexer.nextToken()) != null && token.getType() != token.EOF)) {
- switch (token.getType()) {
- case JavaLexer.LBRACE:
- advance++;
- break;
- case JavaParser.RBRACE:
- advance--;
- break;
- }
- }
- advance = Math.max(0, advance);
- return advance * getTabSize();
- } catch (Throwable e) {
- LOG.error("Error calculating indent advance", e);
- }
-
- return 0;
- }
-
- @Override
- public SymbolPairMatch getSymbolPairs() {
- return new JavaSymbolPairs();
- }
-
@NonNull
@Override
public AnalyzeManager getAnalyzeManager() {
@@ -127,11 +97,41 @@ public class JavaLanguage extends IDELanguage {
return getIndentAdvance(content.getLine(line).substring(0, column));
}
+ @Override
+ public int getIndentAdvance(@NonNull String line) {
+ try {
+ JavaLexer lexer = new JavaLexer(CharStreams.fromReader(new StringReader(line)));
+ Token token;
+ int advance = 0;
+ while (((token = lexer.nextToken()) != null && token.getType() != token.EOF)) {
+ switch (token.getType()) {
+ case JavaLexer.LBRACE:
+ advance++;
+ break;
+ case JavaParser.RBRACE:
+ advance--;
+ break;
+ }
+ }
+ advance = Math.max(0, advance);
+ return advance * getTabSize();
+ } catch (Throwable e) {
+ LOG.error("Error calculating indent advance", e);
+ }
+
+ return 0;
+ }
+
@Override
protected ILanguageServer getLanguageServer() {
return StudioApp.getInstance().getJavaLanguageServer();
}
+ @Override
+ public SymbolPairMatch getSymbolPairs() {
+ return new JavaSymbolPairs();
+ }
+
@Override
public NewlineHandler[] getNewlineHandlers() {
return newlineHandlers;
diff --git a/app/src/main/java/com/itsaky/androidide/language/kotlin/KotlinAnalyzer.kt b/app/src/main/java/com/itsaky/androidide/language/kotlin/KotlinAnalyzer.kt
index cc9a9df8f..5b4996c31 100644
--- a/app/src/main/java/com/itsaky/androidide/language/kotlin/KotlinAnalyzer.kt
+++ b/app/src/main/java/com/itsaky/androidide/language/kotlin/KotlinAnalyzer.kt
@@ -29,10 +29,8 @@ import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.forComment
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.forKeyword
import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE.forString
import io.github.rosemoe.sora.lang.analysis.IncrementalAnalyzeManager.LineTokenizeResult
-import io.github.rosemoe.sora.lang.styling.CodeBlock
import io.github.rosemoe.sora.lang.styling.Span
import io.github.rosemoe.sora.lang.styling.TextStyle.makeStyle
-import io.github.rosemoe.sora.text.Content
/**
* Incremental syntax analyzer for Kotlin.
diff --git a/app/src/main/java/com/itsaky/androidide/language/kotlin/KotlinLanguage.java b/app/src/main/java/com/itsaky/androidide/language/kotlin/KotlinLanguage.java
index 26cc0da19..ac4eb62ae 100644
--- a/app/src/main/java/com/itsaky/androidide/language/kotlin/KotlinLanguage.java
+++ b/app/src/main/java/com/itsaky/androidide/language/kotlin/KotlinLanguage.java
@@ -22,15 +22,14 @@ import android.os.Bundle;
import androidx.annotation.NonNull;
import com.itsaky.androidide.language.IDELanguage;
-
+import com.itsaky.androidide.lexers.kotlin.KotlinLexer;
+import com.itsaky.androidide.lexers.kotlin.KotlinParser;
import com.itsaky.androidide.utils.ILogger;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.Token;
import java.io.StringReader;
-import com.itsaky.androidide.lexers.kotlin.KotlinLexer;
-import com.itsaky.androidide.lexers.kotlin.KotlinParser;
import io.github.rosemoe.sora.lang.analysis.AnalyzeManager;
import io.github.rosemoe.sora.lang.completion.CompletionCancelledException;
@@ -45,42 +44,13 @@ import io.github.rosemoe.sora.widget.SymbolPairMatch;
public class KotlinLanguage extends IDELanguage {
private static final ILogger LOG = ILogger.newInstance("KotlinLanguage");
- private KotlinAnalyzer analyzer;
private final NewlineHandler[] newlineHandlers = new NewlineHandler[] {new BraceHandler()};
+ private KotlinAnalyzer analyzer;
public KotlinLanguage() {
analyzer = new KotlinAnalyzer();
}
- @Override
- public int getIndentAdvance(@NonNull String line) {
- try {
- KotlinLexer lexer = new KotlinLexer(CharStreams.fromReader(new StringReader(line)));
- Token token;
- int advance = 0;
- while (((token = lexer.nextToken()) != null && token.getType() != token.EOF)) {
- switch (token.getType()) {
- case KotlinParser.LCURL:
- advance++;
- break;
- case KotlinParser.RCURL:
- advance--;
- break;
- }
- }
- advance = Math.max(0, advance);
- return advance * getTabSize();
- } catch (Throwable e) {
- LOG.error("Error calculating indent advance", e);
- }
- return 0;
- }
-
- @Override
- public SymbolPairMatch getSymbolPairs() {
- return new KotlinSymbolPairs();
- }
-
@NonNull
@Override
public AnalyzeManager getAnalyzeManager() {
@@ -109,8 +79,8 @@ public class KotlinLanguage extends IDELanguage {
}
@Override
- public CharSequence format(CharSequence content) {
- return content;
+ public SymbolPairMatch getSymbolPairs() {
+ return new KotlinSymbolPairs();
}
@Override
@@ -123,6 +93,35 @@ public class KotlinLanguage extends IDELanguage {
analyzer = null;
}
+ @Override
+ public CharSequence format(CharSequence content) {
+ return content;
+ }
+
+ @Override
+ public int getIndentAdvance(@NonNull String line) {
+ try {
+ KotlinLexer lexer = new KotlinLexer(CharStreams.fromReader(new StringReader(line)));
+ Token token;
+ int advance = 0;
+ while (((token = lexer.nextToken()) != null && token.getType() != token.EOF)) {
+ switch (token.getType()) {
+ case KotlinParser.LCURL:
+ advance++;
+ break;
+ case KotlinParser.RCURL:
+ advance--;
+ break;
+ }
+ }
+ advance = Math.max(0, advance);
+ return advance * getTabSize();
+ } catch (Throwable e) {
+ LOG.error("Error calculating indent advance", e);
+ }
+ return 0;
+ }
+
private static class KotlinSymbolPairs extends SymbolPairMatch {
public KotlinSymbolPairs() {
super.putPair('{', new Replacement("{}", 1));
diff --git a/app/src/main/java/com/itsaky/androidide/language/xml/XMLLanguage.java b/app/src/main/java/com/itsaky/androidide/language/xml/XMLLanguage.java
index 1aa2faab2..f4a6bfd3c 100755
--- a/app/src/main/java/com/itsaky/androidide/language/xml/XMLLanguage.java
+++ b/app/src/main/java/com/itsaky/androidide/language/xml/XMLLanguage.java
@@ -57,38 +57,6 @@ public class XMLLanguage extends IDELanguage {
this.newlineHandlers = new NewlineHandler[0];
}
- @Override
- public int getIndentAdvance(@NonNull String content) {
- try {
- XMLLexer lexer = new XMLLexer(CharStreams.fromReader(new StringReader(content)));
- Token token;
- int advance = 0;
- while (((token = lexer.nextToken()) != null && token.getType() != token.EOF)) {
- switch (token.getType()) {
- case XMLLexer.OPEN:
- advance++;
- break;
- case XMLLexer.CLOSE:
- case XMLLexer.SLASH_CLOSE:
- advance--;
- break;
- default:
- break;
- }
- }
- advance = Math.max(0, advance);
- return advance * getTabSize();
- } catch (Throwable e) {
- LOG.error("Failed to compute indent advance", e);
- }
- return 0;
- }
-
- @Override
- public SymbolPairMatch getSymbolPairs() {
- return new SymbolPairMatch.DefaultSymbolPairs();
- }
-
@NonNull
@Override
public AnalyzeManager getAnalyzeManager() {
@@ -125,11 +93,43 @@ public class XMLLanguage extends IDELanguage {
return getIndentAdvance(text.trim());
}
+ @Override
+ public int getIndentAdvance(@NonNull String content) {
+ try {
+ XMLLexer lexer = new XMLLexer(CharStreams.fromReader(new StringReader(content)));
+ Token token;
+ int advance = 0;
+ while (((token = lexer.nextToken()) != null && token.getType() != token.EOF)) {
+ switch (token.getType()) {
+ case XMLLexer.OPEN:
+ advance++;
+ break;
+ case XMLLexer.CLOSE:
+ case XMLLexer.SLASH_CLOSE:
+ advance--;
+ break;
+ default:
+ break;
+ }
+ }
+ advance = Math.max(0, advance);
+ return advance * getTabSize();
+ } catch (Throwable e) {
+ LOG.error("Failed to compute indent advance", e);
+ }
+ return 0;
+ }
+
@Override
protected ILanguageServer getLanguageServer() {
return StudioApp.getInstance().getXMLLanguageServer();
}
+ @Override
+ public SymbolPairMatch getSymbolPairs() {
+ return new SymbolPairMatch.DefaultSymbolPairs();
+ }
+
@Override
public NewlineHandler[] getNewlineHandlers() {
return newlineHandlers;
diff --git a/app/src/main/java/com/itsaky/androidide/lsp/IDELanguageClientImpl.java b/app/src/main/java/com/itsaky/androidide/lsp/IDELanguageClientImpl.java
index a903e01c1..a6f48545a 100755
--- a/app/src/main/java/com/itsaky/androidide/lsp/IDELanguageClientImpl.java
+++ b/app/src/main/java/com/itsaky/androidide/lsp/IDELanguageClientImpl.java
@@ -19,7 +19,6 @@
*/
package com.itsaky.androidide.lsp;
-import android.os.Trace;
import android.view.View;
import androidx.annotation.NonNull;
@@ -73,25 +72,20 @@ import io.github.rosemoe.sora.text.Content;
/** AndroidIDE specific implementation of the LanguageClient */
public class IDELanguageClientImpl implements ILanguageClient {
+ public static final int MAX_DIAGNOSTIC_FILES = 10;
+ public static final int MAX_DIAGNOSTIC_ITEMS_PER_FILE = 20;
protected static final Gson gson = new Gson();
protected static final ILogger LOG = ILogger.newInstance("AbstractLanguageClient");
private static IDELanguageClientImpl mInstance;
private final Map> diagnostics = new HashMap<>();
protected EditorActivityProvider activityProvider;
- public static final int MAX_DIAGNOSTIC_FILES = 10;
- public static final int MAX_DIAGNOSTIC_ITEMS_PER_FILE = 20;
-
private IDELanguageClientImpl(EditorActivityProvider provider) {
setActivityProvider(provider);
}
- public static IDELanguageClientImpl getInstance() {
- if (mInstance == null) {
- throw new IllegalStateException("Client not initialized");
- }
-
- return mInstance;
+ public void setActivityProvider(EditorActivityProvider provider) {
+ this.activityProvider = provider;
}
public static IDELanguageClientImpl initialize(EditorActivityProvider provider) {
@@ -104,6 +98,14 @@ public class IDELanguageClientImpl implements ILanguageClient {
return getInstance();
}
+ public static IDELanguageClientImpl getInstance() {
+ if (mInstance == null) {
+ throw new IllegalStateException("Client not initialized");
+ }
+
+ return mInstance;
+ }
+
public static void shutdown() {
mInstance = null;
}
@@ -112,19 +114,6 @@ public class IDELanguageClientImpl implements ILanguageClient {
return mInstance != null;
}
- public void setActivityProvider(EditorActivityProvider provider) {
- this.activityProvider = provider;
- }
-
- protected EditorActivity activity() {
- if (activityProvider == null) return null;
- return activityProvider.provide();
- }
-
- private CodeEditorView findEditorByFile(File file) {
- return activity().getEditorForFile(file);
- }
-
public void hideDiagnostics() {
if (activity() == null || activity().getDiagnosticBinding() == null) {
return;
@@ -133,21 +122,6 @@ public class IDELanguageClientImpl implements ILanguageClient {
activity().getDiagnosticBinding().getRoot().setVisibility(View.GONE);
}
- private void hideBottomDiagnosticView(final File file) {
- if (activity() == null || file == null) {
- return;
- }
-
- final var frag = findEditorByFile(file);
- if (frag == null || frag.getBinding() == null) {
- return;
- }
-
- frag.getBinding().diagnosticTextContainer.setVisibility(View.GONE);
- frag.getBinding().diagnosticText.setVisibility(View.GONE);
- frag.getBinding().diagnosticText.setClickable(false);
- }
-
@Override
public void publishDiagnostics(DiagnosticResult result) {
boolean error = result == null;
@@ -181,66 +155,17 @@ public class IDELanguageClientImpl implements ILanguageClient {
activity().setDiagnosticsAdapter(newDiagnosticsAdapter());
}
+ protected EditorActivity activity() {
+ if (activityProvider == null) return null;
+ return activityProvider.provide();
+ }
+
@Nullable
@Override
public DiagnosticItem getDiagnosticAt(final File file, final int line, final int column) {
return DiagnosticUtil.binarySearchDiagnostic(this.diagnostics.get(file), line, column);
}
- /** Called by {@link IDEEditor IDEEditor} to show locations in EditorActivity */
- public void showLocations(List locations) {
-
- // Cannot show anything if the activity() is null
- if (activity() == null) {
- return;
- }
-
- boolean error = locations == null || locations.isEmpty();
- activity().handleSearchResultVisibility(error);
-
- if (error) {
- activity().setSearchResultAdapter(new SearchListAdapter(null, null, null));
- return;
- }
-
- final Map> results = new HashMap<>();
- for (int i = 0; i < locations.size(); i++) {
- try {
- final Location loc = locations.get(i);
- if (loc == null) {
- continue;
- }
-
- final File file = loc.getFile().toFile();
- if (!file.exists() || !file.isFile()) continue;
- var frag = findEditorByFile(file);
- Content content;
- if (frag != null && frag.getEditor() != null) content = frag.getEditor().getText();
- else content = new Content(FileIOUtils.readFile2String(file));
- final List matches =
- results.containsKey(file) ? results.get(file) : new ArrayList<>();
- Objects.requireNonNull(matches)
- .add(
- new SearchResult(
- loc.getRange(),
- file,
- content.getLineString(loc.getRange().getStart().getLine()),
- content
- .subContent(
- loc.getRange().getStart().getLine(),
- loc.getRange().getStart().getColumn(),
- loc.getRange().getEnd().getLine(),
- loc.getRange().getEnd().getColumn())
- .toString()));
- results.put(file, matches);
- } catch (Throwable th) {
- LOG.error("Failed to show file location", th);
- }
- }
-
- activity().handleSearchResults(results);
- }
-
@Override
public void performCodeAction(File file, CodeActionItem actionItem) {
final var editor = activity().getEditorForFile(file);
@@ -289,6 +214,108 @@ public class IDELanguageClientImpl implements ILanguageClient {
});
}
+ private Boolean performCodeActionAsync(final IDEEditor editor, final CodeActionItem action) {
+ LOG.debug("Performing code action:", action);
+ final var changes = action.getChanges();
+ if (changes.isEmpty()) {
+ return Boolean.FALSE;
+ }
+
+ for (var change : changes) {
+ final var path = change.getFile();
+ if (path == null) {
+ continue;
+ }
+
+ final File file = path.toFile();
+ if (!file.exists()) {
+ continue;
+ }
+
+ for (TextEdit edit : change.getEdits()) {
+ final String editorFilepath =
+ editor.getFile() == null ? "" : editor.getFile().getAbsolutePath();
+ if (file.getAbsolutePath().equals(editorFilepath)) {
+ // Edit is in the same editor which requested the code action
+ editInEditor(editor, edit);
+ } else {
+ var openedFrag = findEditorByFile(file);
+
+ if (openedFrag != null && openedFrag.getEditor() != null) {
+ // Edit is in another 'opened' file
+ editInEditor(openedFrag.getEditor(), edit);
+ } else {
+ // Edit is in some other file which is not opened
+ // We should open that file and perform the edit
+ openedFrag = activity().openFile(file);
+ if (openedFrag != null && openedFrag.getEditor() != null) {
+ editInEditor(openedFrag.getEditor(), edit);
+ }
+ }
+ }
+ }
+ }
+
+ return Boolean.TRUE;
+ }
+
+ private void editInEditor(final IDEEditor editor, final TextEdit edit) {
+ final Range range = edit.getRange();
+ final int startLine = range.getStart().getLine();
+ final int startCol = range.getStart().getColumn();
+ final int endLine = range.getEnd().getLine();
+ final int endCol = range.getEnd().getColumn();
+
+ activity()
+ .runOnUiThread(
+ () -> {
+ if (startLine == endLine && startCol == endCol) {
+ editor.getText().insert(startLine, startCol, edit.getNewText());
+ } else {
+ editor.getText().replace(startLine, startCol, endLine, endCol, edit.getNewText());
+ }
+ });
+ }
+
+ @Override
+ public com.itsaky.lsp.models.ShowDocumentResult showDocument(
+ com.itsaky.lsp.models.ShowDocumentParams params) {
+ boolean success = false;
+ final var result = new com.itsaky.lsp.models.ShowDocumentResult(false);
+ if (activity() == null) {
+ return result;
+ }
+
+ if (params != null) {
+ File file = params.getFile().toFile();
+ if (file.exists() && file.isFile() && FileUtils.isUtf8(file)) {
+ final var range = params.getSelection();
+ var frag =
+ activity().getEditorAtIndex(activity().getBinding().tabs.getSelectedTabPosition());
+ if (frag != null
+ && frag.getFile() != null
+ && frag.getEditor() != null
+ && frag.getFile().getAbsolutePath().equals(file.getAbsolutePath())) {
+ if (LSPUtils.isEqual(range.getStart(), range.getEnd())) {
+ frag.getEditor().setSelection(range.getStart().getLine(), range.getStart().getColumn());
+ } else {
+ frag.getEditor().setSelection(range);
+ }
+ } else {
+ activity().openFileAndSelect(file, range);
+ }
+ success = true;
+ }
+ }
+
+ result.setSuccess(success);
+ return result;
+ }
+
+ public DiagnosticsAdapter newDiagnosticsAdapter() {
+ return new DiagnosticsAdapter(mapAsGroup(this.diagnostics), activity());
+ }
+
private List mapAsGroup(Map> map) {
final var groups = new ArrayList();
var diagnosticMap = map;
@@ -364,6 +391,79 @@ public class IDELanguageClientImpl implements ILanguageClient {
return result;
}
+ /** Called by {@link IDEEditor IDEEditor} to show locations in EditorActivity */
+ public void showLocations(List locations) {
+
+ // Cannot show anything if the activity() is null
+ if (activity() == null) {
+ return;
+ }
+
+ boolean error = locations == null || locations.isEmpty();
+ activity().handleSearchResultVisibility(error);
+
+ if (error) {
+ activity().setSearchResultAdapter(new SearchListAdapter(null, null, null));
+ return;
+ }
+
+ final Map> results = new HashMap<>();
+ for (int i = 0; i < locations.size(); i++) {
+ try {
+ final Location loc = locations.get(i);
+ if (loc == null) {
+ continue;
+ }
+
+ final File file = loc.getFile().toFile();
+ if (!file.exists() || !file.isFile()) continue;
+ var frag = findEditorByFile(file);
+ Content content;
+ if (frag != null && frag.getEditor() != null) content = frag.getEditor().getText();
+ else content = new Content(FileIOUtils.readFile2String(file));
+ final List matches =
+ results.containsKey(file) ? results.get(file) : new ArrayList<>();
+ Objects.requireNonNull(matches)
+ .add(
+ new SearchResult(
+ loc.getRange(),
+ file,
+ content.getLineString(loc.getRange().getStart().getLine()),
+ content
+ .subContent(
+ loc.getRange().getStart().getLine(),
+ loc.getRange().getStart().getColumn(),
+ loc.getRange().getEnd().getLine(),
+ loc.getRange().getEnd().getColumn())
+ .toString()));
+ results.put(file, matches);
+ } catch (Throwable th) {
+ LOG.error("Failed to show file location", th);
+ }
+ }
+
+ activity().handleSearchResults(results);
+ }
+
+ private CodeEditorView findEditorByFile(File file) {
+ return activity().getEditorForFile(file);
+ }
+
+ private void hideBottomDiagnosticView(final File file) {
+ if (activity() == null || file == null) {
+ return;
+ }
+
+ final var frag = findEditorByFile(file);
+ if (frag == null || frag.getBinding() == null) {
+ return;
+ }
+
+ frag.getBinding().diagnosticTextContainer.setVisibility(View.GONE);
+ frag.getBinding().diagnosticText.setVisibility(View.GONE);
+ frag.getBinding().diagnosticText.setClickable(false);
+ }
+
private void showAvailableQuickfixes(IDEEditor editor, List actions) {
final MaterialAlertDialogBuilder builder = DialogUtils.newMaterialDialogBuilder(activity());
builder.setTitle(R.string.msg_code_actions);
@@ -386,109 +486,7 @@ public class IDELanguageClientImpl implements ILanguageClient {
return arr;
}
- private Boolean performCodeActionAsync(final IDEEditor editor, final CodeActionItem action) {
- LOG.debug("Performing code action:", action);
- final var changes = action.getChanges();
- if (changes.isEmpty()) {
- return Boolean.FALSE;
- }
-
- for (var change : changes) {
- final var path = change.getFile();
- if (path == null) {
- continue;
- }
-
- final File file = path.toFile();
- if (!file.exists()) {
- continue;
- }
-
- for (TextEdit edit : change.getEdits()) {
- final String editorFilepath =
- editor.getFile() == null ? "" : editor.getFile().getAbsolutePath();
- if (file.getAbsolutePath().equals(editorFilepath)) {
- // Edit is in the same editor which requested the code action
- editInEditor(editor, edit);
- } else {
- var openedFrag = findEditorByFile(file);
-
- if (openedFrag != null && openedFrag.getEditor() != null) {
- // Edit is in another 'opened' file
- editInEditor(openedFrag.getEditor(), edit);
- } else {
- // Edit is in some other file which is not opened
- // We should open that file and perform the edit
- openedFrag = activity().openFile(file);
- if (openedFrag != null && openedFrag.getEditor() != null) {
- editInEditor(openedFrag.getEditor(), edit);
- }
- }
- }
- }
- }
-
- return Boolean.TRUE;
- }
-
private void execCommand(IDEEditor editor, Command command) {
editor.executeCommand(command);
}
-
- private void editInEditor(final IDEEditor editor, final TextEdit edit) {
- final Range range = edit.getRange();
- final int startLine = range.getStart().getLine();
- final int startCol = range.getStart().getColumn();
- final int endLine = range.getEnd().getLine();
- final int endCol = range.getEnd().getColumn();
-
- activity()
- .runOnUiThread(
- () -> {
- if (startLine == endLine && startCol == endCol) {
- editor.getText().insert(startLine, startCol, edit.getNewText());
- } else {
- editor.getText().replace(startLine, startCol, endLine, endCol, edit.getNewText());
- }
- });
- }
-
- public DiagnosticsAdapter newDiagnosticsAdapter() {
- return new DiagnosticsAdapter(mapAsGroup(this.diagnostics), activity());
- }
-
- @Override
- public com.itsaky.lsp.models.ShowDocumentResult showDocument(
- com.itsaky.lsp.models.ShowDocumentParams params) {
- boolean success = false;
- final var result = new com.itsaky.lsp.models.ShowDocumentResult(false);
- if (activity() == null) {
- return result;
- }
-
- if (params != null) {
- File file = params.getFile().toFile();
- if (file.exists() && file.isFile() && FileUtils.isUtf8(file)) {
- final var range = params.getSelection();
- var frag =
- activity().getEditorAtIndex(activity().getBinding().tabs.getSelectedTabPosition());
- if (frag != null
- && frag.getFile() != null
- && frag.getEditor() != null
- && frag.getFile().getAbsolutePath().equals(file.getAbsolutePath())) {
- if (LSPUtils.isEqual(range.getStart(), range.getEnd())) {
- frag.getEditor().setSelection(range.getStart().getLine(), range.getStart().getColumn());
- } else {
- frag.getEditor().setSelection(range);
- }
- } else {
- activity().openFileAndSelect(file, range);
- }
- success = true;
- }
- }
-
- result.setSuccess(success);
- return result;
- }
}
diff --git a/app/src/main/java/com/itsaky/androidide/models/ApkMetadata.java b/app/src/main/java/com/itsaky/androidide/models/ApkMetadata.java
index 6ac7d9afd..082b9dad1 100755
--- a/app/src/main/java/com/itsaky/androidide/models/ApkMetadata.java
+++ b/app/src/main/java/com/itsaky/androidide/models/ApkMetadata.java
@@ -143,6 +143,10 @@ public class ApkMetadata {
return elements;
}
+ public void setElements(List elements) {
+ this.elements = elements;
+ }
+
public ArtifactType getArtifactType() {
return artifactType;
}
@@ -151,10 +155,6 @@ public class ApkMetadata {
this.artifactType = artifactType;
}
- public void setElements(List elements) {
- this.elements = elements;
- }
-
public int getVersion() {
return version;
}
diff --git a/app/src/main/java/com/itsaky/androidide/models/IconTextListItem.java b/app/src/main/java/com/itsaky/androidide/models/IconTextListItem.java
index 13df30bf4..f008fe92b 100755
--- a/app/src/main/java/com/itsaky/androidide/models/IconTextListItem.java
+++ b/app/src/main/java/com/itsaky/androidide/models/IconTextListItem.java
@@ -21,10 +21,6 @@ import androidx.annotation.DrawableRes;
public interface IconTextListItem {
- String getText();
-
- int getIconResource();
-
public static IconTextListItem create(String name, @DrawableRes int icon) {
return new IconTextListItem() {
@Override
@@ -38,4 +34,8 @@ public interface IconTextListItem {
}
};
}
+
+ String getText();
+
+ int getIconResource();
}
diff --git a/app/src/main/java/com/itsaky/androidide/models/NewProjectDetails.java b/app/src/main/java/com/itsaky/androidide/models/NewProjectDetails.java
index 7d1c82715..5f747284c 100755
--- a/app/src/main/java/com/itsaky/androidide/models/NewProjectDetails.java
+++ b/app/src/main/java/com/itsaky/androidide/models/NewProjectDetails.java
@@ -46,17 +46,12 @@ public class NewProjectDetails {
this.savePath = savePath;
}
- public NewProjectDetails setName(String name) {
- this.name = name;
- return this;
- }
-
public String getName() {
return name;
}
- public NewProjectDetails setPackageName(String packageName) {
- this.packageName = packageName;
+ public NewProjectDetails setName(String name) {
+ this.name = name;
return this;
}
@@ -64,8 +59,8 @@ public class NewProjectDetails {
return packageName;
}
- public NewProjectDetails setMinSdk(int minSdk) {
- this.minSdk = minSdk;
+ public NewProjectDetails setPackageName(String packageName) {
+ this.packageName = packageName;
return this;
}
@@ -73,8 +68,8 @@ public class NewProjectDetails {
return minSdk;
}
- public NewProjectDetails setTargetSdk(int targetSdk) {
- this.targetSdk = targetSdk;
+ public NewProjectDetails setMinSdk(int minSdk) {
+ this.minSdk = minSdk;
return this;
}
@@ -82,12 +77,17 @@ public class NewProjectDetails {
return targetSdk;
}
- public NewProjectDetails setCppFlags(String cppFlags) {
- this.cppFlags = cppFlags;
+ public NewProjectDetails setTargetSdk(int targetSdk) {
+ this.targetSdk = targetSdk;
return this;
}
public String getCppFlags() {
return cppFlags;
}
+
+ public NewProjectDetails setCppFlags(String cppFlags) {
+ this.cppFlags = cppFlags;
+ return this;
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/models/ProjectTemplate.java b/app/src/main/java/com/itsaky/androidide/models/ProjectTemplate.java
index 12fb6d9ee..09f8d1dc4 100755
--- a/app/src/main/java/com/itsaky/androidide/models/ProjectTemplate.java
+++ b/app/src/main/java/com/itsaky/androidide/models/ProjectTemplate.java
@@ -42,39 +42,43 @@ public class ProjectTemplate {
this.imageId = imageId;
}
+ public int getId() {
+ return id;
+ }
+
public ProjectTemplate setId(int id) {
this.id = id;
return this;
}
- public int getId() {
- return id;
- }
-
public ProjectTemplate setName(Context ctx, @StringRes int name) {
return setName(ctx.getString(name));
}
+ public String getName() {
+ return name;
+ }
+
public ProjectTemplate setName(String name) {
this.name = name;
return this;
}
- public String getName() {
- return name;
- }
-
public ProjectTemplate setDescription(Context ctx, @StringRes int desc) {
return setDescription(ctx.getString(desc));
}
+ public String getDescription() {
+ return description;
+ }
+
public ProjectTemplate setDescription(String description) {
this.description = description;
return this;
}
- public String getDescription() {
- return description;
+ public int getImageId() {
+ return imageId;
}
public ProjectTemplate setImageId(@DrawableRes int imageId) {
@@ -82,10 +86,6 @@ public class ProjectTemplate {
return this;
}
- public int getImageId() {
- return imageId;
- }
-
public boolean isSupportJava() {
return this.isSupportJava;
}
diff --git a/app/src/main/java/com/itsaky/androidide/models/UIWidget.java b/app/src/main/java/com/itsaky/androidide/models/UIWidget.java
index 7a1c496e4..4b38c34d7 100755
--- a/app/src/main/java/com/itsaky/androidide/models/UIWidget.java
+++ b/app/src/main/java/com/itsaky/androidide/models/UIWidget.java
@@ -32,9 +32,20 @@ import java.util.Objects;
*/
public class UIWidget implements IconTextListItem, Parcelable {
+ public static final Creator CREATOR =
+ new Creator() {
+ @Override
+ public UIWidget createFromParcel(Parcel in) {
+ return new UIWidget(in);
+ }
+
+ @Override
+ public UIWidget[] newArray(int size) {
+ return new UIWidget[size];
+ }
+ };
private final String name;
private final int icon;
-
private final String clazz;
private UIWidget(Parcel in) {
@@ -49,25 +60,9 @@ public class UIWidget implements IconTextListItem, Parcelable {
this.clazz = clazz.getName();
}
- public static final Creator CREATOR =
- new Creator() {
- @Override
- public UIWidget createFromParcel(Parcel in) {
- return new UIWidget(in);
- }
-
- @Override
- public UIWidget[] newArray(int size) {
- return new UIWidget[size];
- }
- };
-
- public String getName() {
- return name;
- }
-
- public int getIcon() {
- return icon;
+ @Override
+ public int hashCode() {
+ return Objects.hash(getName(), getIcon(), clazz);
}
@Override
@@ -80,9 +75,12 @@ public class UIWidget implements IconTextListItem, Parcelable {
&& clazz.equals(widget.clazz);
}
- @Override
- public int hashCode() {
- return Objects.hash(getName(), getIcon(), clazz);
+ public String getName() {
+ return name;
+ }
+
+ public int getIcon() {
+ return icon;
}
/**
diff --git a/app/src/main/java/com/itsaky/androidide/models/UIWidgetGroup.java b/app/src/main/java/com/itsaky/androidide/models/UIWidgetGroup.java
index 168dcdebc..fa1fb3b0a 100755
--- a/app/src/main/java/com/itsaky/androidide/models/UIWidgetGroup.java
+++ b/app/src/main/java/com/itsaky/androidide/models/UIWidgetGroup.java
@@ -38,27 +38,6 @@ import java.util.Objects;
*/
public class UIWidgetGroup implements IconTextListItem, Parcelable {
- /** Name of this group. */
- private final String name;
-
- /** Children of this group. */
- private final List children;
-
- /** Is this group currently selected in the group list? */
- private boolean selected;
-
- public UIWidgetGroup(String name) {
- this.name = name;
- this.selected = false;
- this.children = new ArrayList<>();
- }
-
- protected UIWidgetGroup(@NonNull Parcel in) {
- this.name = in.readString();
- this.children = in.createTypedArrayList(UIWidget.CREATOR);
- this.selected = in.readByte() != 0;
- }
-
public static final Creator CREATOR =
new Creator() {
@@ -76,32 +55,23 @@ public class UIWidgetGroup implements IconTextListItem, Parcelable {
return new UIWidgetGroup[size];
}
};
+ /** Name of this group. */
+ private final String name;
+ /** Children of this group. */
+ private final List children;
+ /** Is this group currently selected in the group list? */
+ private boolean selected;
- /**
- * Get the name of this group.
- *
- * @return The name of this group.
- */
- public String getName() {
- return name;
+ public UIWidgetGroup(String name) {
+ this.name = name;
+ this.selected = false;
+ this.children = new ArrayList<>();
}
- /**
- * Get the children of this group.
- *
- * @return The children.
- */
- @NonNull
- public List getChildren() {
- return children;
- }
-
- public void setSelected(boolean selected) {
- this.selected = selected;
- }
-
- public boolean isSelected() {
- return selected;
+ protected UIWidgetGroup(@NonNull Parcel in) {
+ this.name = in.readString();
+ this.children = in.createTypedArrayList(UIWidget.CREATOR);
+ this.selected = in.readByte() != 0;
}
/**
@@ -129,6 +99,11 @@ public class UIWidgetGroup implements IconTextListItem, Parcelable {
return children.get(index);
}
+ @Override
+ public int hashCode() {
+ return Objects.hash(getName(), getChildren(), isSelected());
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -139,9 +114,31 @@ public class UIWidgetGroup implements IconTextListItem, Parcelable {
&& getChildren().equals(group.getChildren());
}
- @Override
- public int hashCode() {
- return Objects.hash(getName(), getChildren(), isSelected());
+ /**
+ * Get the name of this group.
+ *
+ * @return The name of this group.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Get the children of this group.
+ *
+ * @return The children.
+ */
+ @NonNull
+ public List getChildren() {
+ return children;
+ }
+
+ public boolean isSelected() {
+ return selected;
+ }
+
+ public void setSelected(boolean selected) {
+ this.selected = selected;
}
@Override
diff --git a/app/src/main/java/com/itsaky/androidide/models/XMLAttribute.java b/app/src/main/java/com/itsaky/androidide/models/XMLAttribute.java
index c2163f4a1..fbab725f5 100644
--- a/app/src/main/java/com/itsaky/androidide/models/XMLAttribute.java
+++ b/app/src/main/java/com/itsaky/androidide/models/XMLAttribute.java
@@ -114,14 +114,6 @@ public class XMLAttribute extends UiAttribute implements Parcelable {
return new XMLAttribute(INamespace.ANDROID, name, "", false);
}
- public int getFormat() {
- return format;
- }
-
- public void setFormat(int format) {
- this.format = format;
- }
-
public int findFormat() {
if (getFormat() > 0) {
@@ -137,20 +129,18 @@ public class XMLAttribute extends UiAttribute implements Parcelable {
return getFormat();
}
+ public int getFormat() {
+ return format;
+ }
+
+ public void setFormat(int format) {
+ this.format = format;
+ }
+
public boolean hasFormat(int format) {
return (this.format & format) != 0;
}
- public Attr getAttr() {
- return attr;
- }
-
- public void setAttr(Attr attr) {
- Objects.requireNonNull(attr);
- this.attr = attr;
- setFormat(attr.format);
- }
-
@Override
public void apply(String value) {
super.apply(value);
@@ -175,4 +165,14 @@ public class XMLAttribute extends UiAttribute implements Parcelable {
dest.writeParcelable(getAttr(), flags);
dest.writeInt(this.format);
}
+
+ public Attr getAttr() {
+ return attr;
+ }
+
+ public void setAttr(Attr attr) {
+ Objects.requireNonNull(attr);
+ this.attr = attr;
+ setFormat(attr.format);
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/projects/CachingProject.kt b/app/src/main/java/com/itsaky/androidide/projects/CachingProject.kt
index 9b832d5e7..5416fece2 100644
--- a/app/src/main/java/com/itsaky/androidide/projects/CachingProject.kt
+++ b/app/src/main/java/com/itsaky/androidide/projects/CachingProject.kt
@@ -36,120 +36,121 @@ import java.util.concurrent.*
*/
class CachingProject(val project: IProject) : IProject {
- private val log = ILogger.newInstance(javaClass.simpleName)
+ private val log = ILogger.newInstance(javaClass.simpleName)
- private val mName: String by lazy { this.project.name.get() }
- private val mDescription: String by lazy { this.project.description.get() }
- private val mProjectPath: String by lazy { this.project.projectPath.get() }
- private val mProjectDir: File by lazy { this.project.projectDir.get() }
- private val mBuildDir: File by lazy { this.project.buildDir.get() }
- private val mBuildScript: File by lazy { this.project.buildScript.get() }
- private val mProjectType: Type by lazy { this.project.type.get() }
+ private val mName: String by lazy { this.project.name.get() }
+ private val mDescription: String by lazy { this.project.description.get() }
+ private val mProjectPath: String by lazy { this.project.projectPath.get() }
+ private val mProjectDir: File by lazy { this.project.projectDir.get() }
+ private val mBuildDir: File by lazy { this.project.buildDir.get() }
+ private val mBuildScript: File by lazy { this.project.buildScript.get() }
+ private val mProjectType: Type by lazy { this.project.type.get() }
- private var mFirstAppModule: IdeAndroidModule? = null
- private val mCachedVariants: MutableMap = mutableMapOf()
- private val mModules: MutableList = mutableListOf()
+ private var mFirstAppModule: IdeAndroidModule? = null
+ private val mCachedVariants: MutableMap = mutableMapOf()
+ private val mModules: MutableList = mutableListOf()
- override fun isProjectInitialized(): CompletableFuture {
- return CompletableFuture.completedFuture(true)
- }
+ override fun isProjectInitialized(): CompletableFuture {
+ return CompletableFuture.completedFuture(true)
+ }
- override fun getName(): CompletableFuture {
- return CompletableFuture.completedFuture(this.mName)
- }
+ override fun getName(): CompletableFuture {
+ return CompletableFuture.completedFuture(this.mName)
+ }
- override fun getDescription(): CompletableFuture {
- return CompletableFuture.completedFuture(mDescription)
- }
+ override fun getDescription(): CompletableFuture {
+ return CompletableFuture.completedFuture(mDescription)
+ }
- override fun getProjectPath(): CompletableFuture {
- return CompletableFuture.completedFuture(mProjectPath)
- }
+ override fun getProjectPath(): CompletableFuture {
+ return CompletableFuture.completedFuture(mProjectPath)
+ }
- override fun getType(): CompletableFuture {
- return CompletableFuture.completedFuture(mProjectType)
- }
+ override fun getType(): CompletableFuture {
+ return CompletableFuture.completedFuture(mProjectType)
+ }
- override fun getProjectDir(): CompletableFuture {
- return CompletableFuture.completedFuture(mProjectDir)
- }
+ override fun getProjectDir(): CompletableFuture {
+ return CompletableFuture.completedFuture(mProjectDir)
+ }
- override fun getBuildDir(): CompletableFuture {
- return CompletableFuture.completedFuture(mBuildDir)
- }
+ override fun getBuildDir(): CompletableFuture {
+ return CompletableFuture.completedFuture(mBuildDir)
+ }
- override fun getBuildScript(): CompletableFuture {
- return CompletableFuture.completedFuture(mBuildScript)
- }
+ override fun getBuildScript(): CompletableFuture {
+ return CompletableFuture.completedFuture(mBuildScript)
+ }
- override fun getTasks(): CompletableFuture> {
- return this.project.tasks
- }
+ override fun getTasks(): CompletableFuture> {
+ return this.project.tasks
+ }
- override fun getModules(): CompletableFuture> {
- return this.project.modules
- }
+ override fun getModules(): CompletableFuture> {
+ return this.project.modules
+ }
- override fun listModules(): CompletableFuture> {
- return if (this.mModules.isNotEmpty()) {
- log.debug("Using cached module data...")
- CompletableFuture.completedFuture(mModules)
- } else {
- return this.project.listModules().whenComplete { modules, err ->
- if (err != null || modules == null) {
- log.debug("Unable to fetch module data from tooling server", err)
- return@whenComplete
- }
-
- if (modules.isEmpty()) {
- log.debug("Empty module data returned by tooling server. Ignoring...")
- return@whenComplete
- }
-
- mModules.clear()
- mModules.addAll(modules)
- }
- }
- }
-
- override fun getVariantData(request: VariantDataRequest): CompletableFuture {
- val cached = mCachedVariants[request]
- if (cached != null) {
- return CompletableFuture.completedFuture(cached)
+ override fun listModules(): CompletableFuture> {
+ return if (this.mModules.isNotEmpty()) {
+ log.debug("Using cached module data...")
+ CompletableFuture.completedFuture(mModules)
+ } else {
+ return this.project.listModules().whenComplete { modules, err ->
+ if (err != null || modules == null) {
+ log.debug("Unable to fetch module data from tooling server", err)
+ return@whenComplete
}
- return this.project.getVariantData(request).whenComplete { t, u ->
- if (t == null) {
- log.warn(
- "Unable to get variant data for " +
- "variant ${request.variantName} ('${request.projectPath}') from tooling server",
- u)
- return@whenComplete
- }
-
- mCachedVariants[request] = t
- }
- }
-
- override fun findByPath(path: String): CompletableFuture {
- return this.project.findByPath(path)
- }
-
- override fun findAndroidModules(): CompletableFuture> {
- return this.project.findAndroidModules()
- }
-
- override fun findFirstAndroidModule(): CompletableFuture {
- return this.project.findFirstAndroidModule()
- }
-
- override fun findFirstAndroidAppModule(): CompletableFuture {
- if (mFirstAppModule != null) {
- return CompletableFuture.completedFuture(mFirstAppModule)
+ if (modules.isEmpty()) {
+ log.debug("Empty module data returned by tooling server. Ignoring...")
+ return@whenComplete
}
- return this.project.findFirstAndroidAppModule().whenComplete { module, _ ->
- this.mFirstAppModule = module
- }
+ mModules.clear()
+ mModules.addAll(modules)
+ }
}
+ }
+
+ override fun getVariantData(request: VariantDataRequest): CompletableFuture {
+ val cached = mCachedVariants[request]
+ if (cached != null) {
+ return CompletableFuture.completedFuture(cached)
+ }
+
+ return this.project.getVariantData(request).whenComplete { t, u ->
+ if (t == null) {
+ log.warn(
+ "Unable to get variant data for " +
+ "variant ${request.variantName} ('${request.projectPath}') from tooling server",
+ u
+ )
+ return@whenComplete
+ }
+
+ mCachedVariants[request] = t
+ }
+ }
+
+ override fun findByPath(path: String): CompletableFuture {
+ return this.project.findByPath(path)
+ }
+
+ override fun findAndroidModules(): CompletableFuture> {
+ return this.project.findAndroidModules()
+ }
+
+ override fun findFirstAndroidModule(): CompletableFuture {
+ return this.project.findFirstAndroidModule()
+ }
+
+ override fun findFirstAndroidAppModule(): CompletableFuture {
+ if (mFirstAppModule != null) {
+ return CompletableFuture.completedFuture(mFirstAppModule)
+ }
+
+ return this.project.findFirstAndroidAppModule().whenComplete { module, _ ->
+ this.mFirstAppModule = module
+ }
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/projects/ProjectManager.kt b/app/src/main/java/com/itsaky/androidide/projects/ProjectManager.kt
index 82eb01480..656c285a0 100644
--- a/app/src/main/java/com/itsaky/androidide/projects/ProjectManager.kt
+++ b/app/src/main/java/com/itsaky/androidide/projects/ProjectManager.kt
@@ -37,171 +37,171 @@ import java.util.concurrent.*
*/
@Suppress("MemberVisibilityCanBePrivate")
object ProjectManager {
- private val log = ILogger.newInstance(javaClass.simpleName)
+ private val log = ILogger.newInstance(javaClass.simpleName)
- var rootProject: IProject? = null
- set(value) {
- field = if (value == null) null else CachingProject(value)
+ var rootProject: IProject? = null
+ set(value) {
+ field = if (value == null) null else CachingProject(value)
- // Cache the module data in advance for future use
- if (field != null) {
- field!!.listModules()
- }
- }
- var projectPath: String? = null
+ // Cache the module data in advance for future use
+ if (field != null) {
+ field!!.listModules()
+ }
+ }
+ var projectPath: String? = null
- fun isInitialized() = this.rootProject != null && this.rootProject!!.isProjectInitialized.get()
+ fun isInitialized() = this.rootProject != null && this.rootProject!!.isProjectInitialized.get()
- fun checkInit(): Boolean {
- if (isInitialized()) {
- return true
- }
-
- log.warn("Project is not initialized yet!")
- return false
+ fun checkInit(): Boolean {
+ if (isInitialized()) {
+ return true
}
- fun getProjectDir(): File? = if (!checkInit()) null else File(getProjectDirPath()!!)
+ log.warn("Project is not initialized yet!")
+ return false
+ }
- fun getProjectDirPath(): String? {
- return projectPath
+ fun getProjectDir(): File? = if (!checkInit()) null else File(getProjectDirPath()!!)
+
+ fun getProjectDirPath(): String? {
+ return projectPath
+ }
+
+ fun generateSources(builder: BuildService?) {
+ if (builder == null) {
+ log.warn("Cannot generate sources. BuildService is null.")
+ return
}
- fun generateSources(builder: BuildService?) {
- if (builder == null) {
- log.warn("Cannot generate sources. BuildService is null.")
- return
- }
+ getApplicationModule().whenCompleteAsync { app, _ ->
+ if (app == null) {
+ log.warn("Cannot run resource and source generation task. No application module found.")
+ return@whenCompleteAsync
+ }
- getApplicationModule().whenCompleteAsync { app, _ ->
- if (app == null) {
- log.warn(
- "Cannot run resource and source generation task. No application module found.")
- return@whenCompleteAsync
- }
+ val debug = app.simpleVariants.firstOrNull { it.name == "debug" }
+ if (debug == null) {
+ log.warn("No debug variant found in application project ${app.name}")
+ return@whenCompleteAsync
+ }
- val debug = app.simpleVariants.firstOrNull { it.name == "debug" }
- if (debug == null) {
- log.warn("No debug variant found in application project ${app.name}")
- return@whenCompleteAsync
- }
+ val mainArtifact = app.simpleVariants.first { it.name == "debug" }.mainArtifact
+ val genResourcesTask = mainArtifact.resGenTaskName
+ val genSourcesTask = mainArtifact.sourceGenTaskName
+ builder
+ .executeProjectTasks(
+ app.projectPath,
+ genResourcesTask ?: "",
+ genSourcesTask,
- val mainArtifact = app.simpleVariants.first { it.name == "debug" }.mainArtifact
- val genResourcesTask = mainArtifact.resGenTaskName
- val genSourcesTask = mainArtifact.sourceGenTaskName
- builder
- .executeProjectTasks(
- app.projectPath,
- genResourcesTask ?: "",
- genSourcesTask,
-
- // If view binding is enabled, generate the view binding classes too
- if (app.viewBindingOptions != null && app.viewBindingOptions!!.isEnabled)
- "dataBindingGenBaseClassesDebug"
- else "")
- .whenComplete { result, taskErr ->
- if (!result.isSuccessful || taskErr != null) {
- log.warn(
- "Execution for tasks '$genResourcesTask' and '$genSourcesTask' failed.",
- taskErr ?: "")
- } else {
- notifyProjectUpdate()
- }
- }
+ // If view binding is enabled, generate the view binding classes too
+ if (app.viewBindingOptions != null && app.viewBindingOptions!!.isEnabled)
+ "dataBindingGenBaseClassesDebug"
+ else ""
+ )
+ .whenComplete { result, taskErr ->
+ if (!result.isSuccessful || taskErr != null) {
+ log.warn(
+ "Execution for tasks '$genResourcesTask' and '$genSourcesTask' failed.",
+ taskErr ?: ""
+ )
+ } else {
+ notifyProjectUpdate()
+ }
}
}
+ }
- fun getApplicationModule(): CompletableFuture {
- if (rootProject == null) {
- log.error(
- "No root project instance is set. Is the project initialization process finished?")
- return CompletableFuture.completedFuture(null)
- }
-
- return rootProject!!.findFirstAndroidAppModule().whenComplete { app, err ->
- if (app == null || err != null) {
- log.debug("An error occurred while fetching model for application module.")
- return@whenComplete
- }
- }
+ fun getApplicationModule(): CompletableFuture {
+ if (rootProject == null) {
+ log.error("No root project instance is set. Is the project initialization process finished?")
+ return CompletableFuture.completedFuture(null)
}
- fun getApplicationResDirectories(): CompletableFuture?> {
- return getApplicationModule().thenApplyAsync {
- if (it == null) null else collectResDirectories(it)
- }
+ return rootProject!!.findFirstAndroidAppModule().whenComplete { app, err ->
+ if (app == null || err != null) {
+ log.debug("An error occurred while fetching model for application module.")
+ return@whenComplete
+ }
+ }
+ }
+
+ fun getApplicationResDirectories(): CompletableFuture?> {
+ return getApplicationModule().thenApplyAsync {
+ if (it == null) null else collectResDirectories(it)
+ }
+ }
+
+ fun notifyProjectUpdate() {
+ log.debug("Updating class paths in language servers...")
+ getApplicationModule().whenCompleteAsync { it, _ ->
+ if (it == null) {
+ log.debug("Cannot find application module. Unable to update class paths to LSP.")
+ return@whenCompleteAsync
+ }
+
+ val server = StudioApp.getInstance().javaLanguageServer
+ val classPaths = collectClassPaths(it)
+ val sourceDirs = collectSourceDirs(it)
+ val configuration = JavaServerConfiguration(classPaths, sourceDirs)
+ server.configurationChanged(configuration)
+ }
+ }
+
+ fun collectResDirectories(android: IdeAndroidModule) =
+ ProjectDataCollector.collectResDirectories(this.rootProject!!, android)
+
+ fun collectClassPaths(app: IdeAndroidModule) =
+ ProjectDataCollector.collectClassPaths(this.rootProject!!, app)
+
+ fun collectSourceDirs(app: IdeAndroidModule): Set =
+ ProjectDataCollector.collectSourceDirs(this.rootProject!!, app)
+
+ @Suppress("unused")
+ fun collectProjectDependencies(project: IProject, app: IdeAndroidModule) =
+ ProjectDataCollector.collectProjectDependencies(project, app)
+
+ @Suppress("unused")
+ fun collectSourceDirs(projects: List) =
+ ProjectDataCollector.collectSourceDirs(projects)
+
+ @Suppress("unused")
+ fun collectSources(java: IdeJavaModule) = ProjectDataCollector.collectSources(java)
+
+ @Suppress("unused")
+ fun collectSources(android: IdeAndroidModule) = ProjectDataCollector.collectSources(android)
+
+ fun findModuleForFile(file: File): CompletableFuture {
+ if (!checkInit()) {
+ return CompletableFuture.completedFuture(null)
}
- fun notifyProjectUpdate() {
- log.debug("Updating class paths in language servers...")
- getApplicationModule().whenCompleteAsync { it, _ ->
- if (it == null) {
- log.debug("Cannot find application module. Unable to update class paths to LSP.")
- return@whenCompleteAsync
+ val notAvailable = ":::::"
+ return rootProject!!
+ .listModules()
+ .thenApplyAsync { modules ->
+ val path = file.canonicalPath
+
+ var longestPath = ""
+ for (module in modules) {
+ val modulePath = module.projectDir.canonicalPath
+ if (path.startsWith(modulePath)) {
+ if (longestPath.length < modulePath.length) {
+ longestPath = modulePath
}
-
- val server = StudioApp.getInstance().javaLanguageServer
- val classPaths = collectClassPaths(it)
- val sourceDirs = collectSourceDirs(it)
- val configuration = JavaServerConfiguration(classPaths, sourceDirs)
- server.configurationChanged(configuration)
- }
- }
-
- fun collectResDirectories(android: IdeAndroidModule) =
- ProjectDataCollector.collectResDirectories(this.rootProject!!, android)
-
- fun collectClassPaths(app: IdeAndroidModule) =
- ProjectDataCollector.collectClassPaths(this.rootProject!!, app)
-
- fun collectSourceDirs(app: IdeAndroidModule): Set =
- ProjectDataCollector.collectSourceDirs(this.rootProject!!, app)
-
- @Suppress("unused")
- fun collectProjectDependencies(project: IProject, app: IdeAndroidModule) =
- ProjectDataCollector.collectProjectDependencies(project, app)
-
- @Suppress("unused")
- fun collectSourceDirs(projects: List) =
- ProjectDataCollector.collectSourceDirs(projects)
-
- @Suppress("unused")
- fun collectSources(java: IdeJavaModule) = ProjectDataCollector.collectSources(java)
-
- @Suppress("unused")
- fun collectSources(android: IdeAndroidModule) = ProjectDataCollector.collectSources(android)
-
- fun findModuleForFile(file: File): CompletableFuture {
- if (!checkInit()) {
- return CompletableFuture.completedFuture(null)
+ }
}
- val notAvailable = ":::::"
- return rootProject!!
- .listModules()
- .thenApplyAsync { modules ->
- val path = file.canonicalPath
+ if (longestPath.isEmpty()) {
+ return@thenApplyAsync notAvailable
+ }
- var longestPath = ""
- for (module in modules) {
- val modulePath = module.projectDir.canonicalPath
- if (path.startsWith(modulePath)) {
- if (longestPath.length < modulePath.length) {
- longestPath = modulePath
- }
- }
- }
-
- if (longestPath.isEmpty()) {
- return@thenApplyAsync notAvailable
- }
-
- return@thenApplyAsync longestPath
- }
- .thenApplyAsync {
- if (it == notAvailable) {
- return@thenApplyAsync null
- } else return@thenApplyAsync rootProject!!.findByPath(it).get()
- }
- }
+ return@thenApplyAsync longestPath
+ }
+ .thenApplyAsync {
+ if (it == notAvailable) {
+ return@thenApplyAsync null
+ } else return@thenApplyAsync rootProject!!.findByPath(it).get()
+ }
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/projects/ProjectResourceTable.java b/app/src/main/java/com/itsaky/androidide/projects/ProjectResourceTable.java
index 5147438ca..102b107e0 100644
--- a/app/src/main/java/com/itsaky/androidide/projects/ProjectResourceTable.java
+++ b/app/src/main/java/com/itsaky/androidide/projects/ProjectResourceTable.java
@@ -80,56 +80,6 @@ public class ProjectResourceTable implements IResourceTable {
return value;
}
- @Override
- public String findBoolean(@NonNull String name) {
- final var table = ValuesTableFactory.getTable(resDir);
-
- if (table == null) {
- return name;
- }
-
- final var resource = table.findBoolean(name);
- if (resource == null) {
- return name;
- }
-
- final var val = resource.getValue();
- if (val.startsWith("@bool/")) {
- final var ref = val.substring("@bool/".length());
- if (ref.equals(name)) {
- // recursive reference
- return name;
- }
- }
-
- return val;
- }
-
- @Override
- public String findInteger(@NonNull String name) {
- final var table = ValuesTableFactory.getTable(resDir);
-
- if (table == null) {
- return name;
- }
-
- final var resource = table.findInteger(name);
- if (resource == null) {
- return name;
- }
-
- final var val = resource.getValue();
- if (val.startsWith("@integer/")) {
- final var ref = val.substring("@integer/".length());
- if (ref.equals(name)) {
- // recursive reference
- return name;
- }
- }
-
- return val;
- }
-
@Override
public String findColor(@NonNull String name) {
final var table = ValuesTableFactory.getTable(resDir);
@@ -193,6 +143,68 @@ public class ProjectResourceTable implements IResourceTable {
return value;
}
+ @Override
+ public String findBoolean(@NonNull String name) {
+ final var table = ValuesTableFactory.getTable(resDir);
+
+ if (table == null) {
+ return name;
+ }
+
+ final var resource = table.findBoolean(name);
+ if (resource == null) {
+ return name;
+ }
+
+ final var val = resource.getValue();
+ if (val.startsWith("@bool/")) {
+ final var ref = val.substring("@bool/".length());
+ if (ref.equals(name)) {
+ // recursive reference
+ return name;
+ }
+ }
+
+ return val;
+ }
+
+ @Override
+ public String findInteger(@NonNull String name) {
+ final var table = ValuesTableFactory.getTable(resDir);
+
+ if (table == null) {
+ return name;
+ }
+
+ final var resource = table.findInteger(name);
+ if (resource == null) {
+ return name;
+ }
+
+ final var val = resource.getValue();
+ if (val.startsWith("@integer/")) {
+ final var ref = val.substring("@integer/".length());
+ if (ref.equals(name)) {
+ // recursive reference
+ return name;
+ }
+ }
+
+ return val;
+ }
+
+ @Override
+ public void setInflatingFile(@NonNull File file) {
+ if (file.getParentFile() == null) {
+ throw new IllegalArgumentException("Invalid inflating file");
+ }
+
+ setupDirectories(
+ file // layout file
+ .getParentFile() // layout dir
+ .getParentFile()); // res dir
+ }
+
@NonNull
@Override
public Collection listResourceNames(@Nullable String type) {
@@ -223,45 +235,6 @@ public class ProjectResourceTable implements IResourceTable {
}
}
- private void listAndAddTo(HashSet set, @NonNull File dir, String type) {
- final var files = dir.listFiles();
- if (files == null) {
- return;
- }
-
- for (var file : files) {
- var name = file.getName();
- if (!name.contains(".")) {
- continue;
- }
-
- name = name.substring(0, name.lastIndexOf('.'));
- name = String.format(Locale.ROOT, "@%s/%s", type, name);
- set.add(name);
- }
- }
-
- @NonNull
- private Collection listAllResourceNames() {
- final var set = new HashSet<>(listResourceNames("color"));
- set.addAll(listResourceNames("drawable"));
- set.addAll(listResourceNames("mipmap"));
- set.addAll(listResourceNames("layout"));
- return set;
- }
-
- @Override
- public void setInflatingFile(@NonNull File file) {
- if (file.getParentFile() == null) {
- throw new IllegalArgumentException("Invalid inflating file");
- }
-
- setupDirectories(
- file // layout file
- .getParentFile() // layout dir
- .getParentFile()); // res dir
- }
-
private void setupDirectories(File resDir) {
if (resDir == null) {
@@ -296,6 +269,33 @@ public class ProjectResourceTable implements IResourceTable {
return null;
}
+ private void listAndAddTo(HashSet set, @NonNull File dir, String type) {
+ final var files = dir.listFiles();
+ if (files == null) {
+ return;
+ }
+
+ for (var file : files) {
+ var name = file.getName();
+ if (!name.contains(".")) {
+ continue;
+ }
+
+ name = name.substring(0, name.lastIndexOf('.'));
+ name = String.format(Locale.ROOT, "@%s/%s", type, name);
+ set.add(name);
+ }
+ }
+
+ @NonNull
+ private Collection listAllResourceNames() {
+ final var set = new HashSet<>(listResourceNames("color"));
+ set.addAll(listResourceNames("drawable"));
+ set.addAll(listResourceNames("mipmap"));
+ set.addAll(listResourceNames("layout"));
+ return set;
+ }
+
private static class NameStartsWith implements FileFilter {
private final String name;
diff --git a/app/src/main/java/com/itsaky/androidide/services/BuildService.kt b/app/src/main/java/com/itsaky/androidide/services/BuildService.kt
index c3b55b04f..e6f4ce41e 100644
--- a/app/src/main/java/com/itsaky/androidide/services/BuildService.kt
+++ b/app/src/main/java/com/itsaky/androidide/services/BuildService.kt
@@ -30,42 +30,42 @@ import java.util.concurrent.*
*/
interface BuildService {
- /**
- * Initialize the project.
- *
- * @param rootDir The root directory of the project to initialize.
- * @return A [CompletableFuture] which returns an [InitializeResult] when the project
- * initialization process finishes.
- */
- fun initializeProject(rootDir: String): CompletableFuture
+ /**
+ * Initialize the project.
+ *
+ * @param rootDir The root directory of the project to initialize.
+ * @return A [CompletableFuture] which returns an [InitializeResult] when the project
+ * initialization process finishes.
+ */
+ fun initializeProject(rootDir: String): CompletableFuture
- /**
- * Execute the given tasks.
- *
- * @param tasks The tasks to execute. If the fully qualified path of the task is not specified,
- * then it will be executed in the root project directory.
- * @return A [CompletableFuture] which returns a list of [TaskExecutionResult]. The result
- * contains a list of tasks that were executed and the result of the whole execution.
- * @see BuildService.executeProjectTasks
- */
- fun executeTasks(vararg tasks: String): CompletableFuture
+ /**
+ * Execute the given tasks.
+ *
+ * @param tasks The tasks to execute. If the fully qualified path of the task is not specified,
+ * then it will be executed in the root project directory.
+ * @return A [CompletableFuture] which returns a list of [TaskExecutionResult]. The result
+ * contains a list of tasks that were executed and the result of the whole execution.
+ * @see BuildService.executeProjectTasks
+ */
+ fun executeTasks(vararg tasks: String): CompletableFuture
- /**
- * Execute the given tasks of the given project.
- *
- * @param projectPath The path of the project. All the tasks will be executed in this project.
- * @param tasks The tasks to execute. These may or may not be fully qualified names of the
- * project. If the task name is not fully qualified, then it will be executed in the given
- * project path. For example, if the project path is ':app' and the task is 'assembleDebug',
- * then, ':app:assembleDebug' task will be executed.
- * @return A [CompletableFuture] which returns a list of [TaskExecutionResult]. The result
- * contains a list of tasks that were executed and the result of the whole execution.
- */
- fun executeProjectTasks(
- projectPath: String,
- vararg tasks: String
- ): CompletableFuture
+ /**
+ * Execute the given tasks of the given project.
+ *
+ * @param projectPath The path of the project. All the tasks will be executed in this project.
+ * @param tasks The tasks to execute. These may or may not be fully qualified names of the
+ * project. If the task name is not fully qualified, then it will be executed in the given project
+ * path. For example, if the project path is ':app' and the task is 'assembleDebug', then,
+ * ':app:assembleDebug' task will be executed.
+ * @return A [CompletableFuture] which returns a list of [TaskExecutionResult]. The result
+ * contains a list of tasks that were executed and the result of the whole execution.
+ */
+ fun executeProjectTasks(
+ projectPath: String,
+ vararg tasks: String
+ ): CompletableFuture
- /** Cancel any running build. */
- fun cancelCurrentBuild(): CompletableFuture
+ /** Cancel any running build. */
+ fun cancelCurrentBuild(): CompletableFuture
}
diff --git a/app/src/main/java/com/itsaky/androidide/services/GradleBuildService.java b/app/src/main/java/com/itsaky/androidide/services/GradleBuildService.java
index 335296fea..2405982c7 100644
--- a/app/src/main/java/com/itsaky/androidide/services/GradleBuildService.java
+++ b/app/src/main/java/com/itsaky/androidide/services/GradleBuildService.java
@@ -321,12 +321,6 @@ public class GradleBuildService extends Service implements BuildService, IToolin
.thenApply(this::markBuildAsFinished);
}
- private String getGradleInstallationPath() {
- return StudioApp.getInstance()
- .getPrefManager()
- .getString(BuildPreferences.KEY_CUSTOM_GRADLE_INSTALLATION, "");
- }
-
@NonNull
@Override
public CompletableFuture executeProjectTasks(
@@ -353,6 +347,12 @@ public class GradleBuildService extends Service implements BuildService, IToolin
return server.cancelCurrentBuild();
}
+ private String getGradleInstallationPath() {
+ return StudioApp.getInstance()
+ .getPrefManager()
+ .getString(BuildPreferences.KEY_CUSTOM_GRADLE_INSTALLATION, "");
+ }
+
private void checkServerStarted() {
if (!isToolingServerStarted) {
throw new IllegalStateException("Tooling API server has not been started");
diff --git a/app/src/main/java/com/itsaky/androidide/services/LogReceiver.java b/app/src/main/java/com/itsaky/androidide/services/LogReceiver.java
index 8d27bf5c2..05626ce5b 100755
--- a/app/src/main/java/com/itsaky/androidide/services/LogReceiver.java
+++ b/app/src/main/java/com/itsaky/androidide/services/LogReceiver.java
@@ -29,12 +29,10 @@ import com.itsaky.androidide.utils.ILogger;
public class LogReceiver extends BroadcastReceiver {
- private LogListener listener;
-
public static final String APPEND_LOG = "com.itsaky.androidide.logs.APPEND_LOG";
public static final String EXTRA_LINE = "log_line";
-
private final ILogger LOG = ILogger.newInstance("LogReceiver");
+ private LogListener listener;
public LogReceiver setLogListener(LogListener listener) {
this.listener = listener;
diff --git a/app/src/main/java/com/itsaky/androidide/tasks/callables/ListDirectoryCallable.java b/app/src/main/java/com/itsaky/androidide/tasks/callables/ListDirectoryCallable.java
index 8d5fad31c..ea2d5c78b 100755
--- a/app/src/main/java/com/itsaky/androidide/tasks/callables/ListDirectoryCallable.java
+++ b/app/src/main/java/com/itsaky/androidide/tasks/callables/ListDirectoryCallable.java
@@ -29,6 +29,14 @@ import java.io.FileFilter;
public class ListDirectoryCallable implements java.util.concurrent.Callable {
+ private final FileFilter ARCHIVE_FILTER =
+ new FileFilter() {
+
+ @Override
+ public boolean accept(File p1) {
+ return p1.isFile() && (p1.getName().endsWith(".tar.xz") || p1.getName().endsWith(".zip"));
+ }
+ };
private File file;
public ListDirectoryCallable(File file) {
@@ -39,13 +47,4 @@ public class ListDirectoryCallable implements java.util.concurrent.Callable new")
+ private IAttribute layoutHeightAttr() {
+ return new UiAttribute(INamespace.ANDROID, "layout_height", "wrap_content");
+ }
+
+ @NonNull
+ @Contract(" -> new")
+ private IAttribute layoutWidthAttr() {
+ return new UiAttribute(INamespace.ANDROID, "layout_width", "wrap_content");
+ }
+
/**
* Finds the index at which the placeholder will be added in the current view group.
*
@@ -180,30 +189,6 @@ public class WidgetDragListener implements View.OnDragListener {
return src;
}
- private RectF leftHalf(RectF src) {
- final RectF result = new RectF(src);
- result.right -= result.width() / 2;
- return src;
- }
-
- private RectF rightHalf(RectF src) {
- final RectF result = new RectF(src);
- result.left += result.width() / 2;
- return src;
- }
-
- @NonNull
- @Contract(" -> new")
- private IAttribute layoutHeightAttr() {
- return new UiAttribute(INamespace.ANDROID, "layout_height", "wrap_content");
- }
-
- @NonNull
- @Contract(" -> new")
- private IAttribute layoutWidthAttr() {
- return new UiAttribute(INamespace.ANDROID, "layout_width", "wrap_content");
- }
-
@NonNull
private IView createView(@NonNull UIWidget widget) {
try {
@@ -223,6 +208,18 @@ public class WidgetDragListener implements View.OnDragListener {
}
}
+ private RectF leftHalf(RectF src) {
+ final RectF result = new RectF(src);
+ result.right -= result.width() / 2;
+ return src;
+ }
+
+ private RectF rightHalf(RectF src) {
+ final RectF result = new RectF(src);
+ result.left += result.width() / 2;
+ return src;
+ }
+
public static interface OnViewAddedListener {
void onViewAdded(IView view);
}
diff --git a/app/src/main/java/com/itsaky/androidide/ui/WidgetTouchListener.java b/app/src/main/java/com/itsaky/androidide/ui/WidgetTouchListener.java
index bbfaf7caa..d45b6f1f8 100644
--- a/app/src/main/java/com/itsaky/androidide/ui/WidgetTouchListener.java
+++ b/app/src/main/java/com/itsaky/androidide/ui/WidgetTouchListener.java
@@ -62,11 +62,6 @@ public class WidgetTouchListener extends GestureDetector.SimpleOnGestureListener
return mGestureDetector.onTouchEvent(motionEvent);
}
- @Override
- public boolean onDown(MotionEvent e) {
- return true; // We would like to get notified about further events.
- }
-
// TODO Should we use onSingleTapConfirmed instead?
@Override
public boolean onSingleTapUp(MotionEvent e) {
@@ -90,6 +85,11 @@ public class WidgetTouchListener extends GestureDetector.SimpleOnGestureListener
}
}
+ @Override
+ public boolean onDown(MotionEvent e) {
+ return true; // We would like to get notified about further events.
+ }
+
/**
* A listener which is invoked when we detect a single click event.
*
diff --git a/app/src/main/java/com/itsaky/androidide/utils/DialogUtils.java b/app/src/main/java/com/itsaky/androidide/utils/DialogUtils.java
index a03f3fdde..b2f923760 100644
--- a/app/src/main/java/com/itsaky/androidide/utils/DialogUtils.java
+++ b/app/src/main/java/com/itsaky/androidide/utils/DialogUtils.java
@@ -34,18 +34,6 @@ import org.jetbrains.annotations.Contract;
*/
public class DialogUtils {
- /**
- * Creates a new MaterialAlertDialogBuilder with the app's default style.
- *
- * @param context The context for the dialog builder.
- * @return The new MaterialAlertDialogBuilder instance.
- */
- @NonNull
- @Contract("_ -> new")
- public static MaterialAlertDialogBuilder newMaterialDialogBuilder(Context context) {
- return new MaterialAlertDialogBuilder(context, R.style.AppTheme_MaterialAlertDialog);
- }
-
/**
* Create a new alert dialog with two buttons: Yes and No . This method
* simply calls {@link #newYesNoDialog(Context, String, String, DialogInterface.OnClickListener,
@@ -98,4 +86,16 @@ public class DialogUtils {
return builder;
}
+
+ /**
+ * Creates a new MaterialAlertDialogBuilder with the app's default style.
+ *
+ * @param context The context for the dialog builder.
+ * @return The new MaterialAlertDialogBuilder instance.
+ */
+ @NonNull
+ @Contract("_ -> new")
+ public static MaterialAlertDialogBuilder newMaterialDialogBuilder(Context context) {
+ return new MaterialAlertDialogBuilder(context, R.style.AppTheme_MaterialAlertDialog);
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/utils/EditorActivityActions.kt b/app/src/main/java/com/itsaky/androidide/utils/EditorActivityActions.kt
index 5f502a39b..b9f1cb0d6 100644
--- a/app/src/main/java/com/itsaky/androidide/utils/EditorActivityActions.kt
+++ b/app/src/main/java/com/itsaky/androidide/utils/EditorActivityActions.kt
@@ -46,39 +46,39 @@ import com.itsaky.androidide.actions.text.UndoAction
* @author Akash Yadav
*/
class EditorActivityActions {
- companion object {
- @JvmStatic
- fun register(context: Context) {
- val registry = ActionsRegistry.getInstance()
+ companion object {
+ @JvmStatic
+ fun register(context: Context) {
+ val registry = ActionsRegistry.getInstance()
- // Toolbar actions
- registry.registerAction(UndoAction(context))
- registry.registerAction(RedoAction(context))
- registry.registerAction(QuickRunAction(context))
- registry.registerAction(RunActionMenu(context))
- registry.registerAction(SaveFileAction(context))
- registry.registerAction(PreviewLayoutAction(context))
- registry.registerAction(FindActionMenu(context))
- registry.registerAction(FileTreeAction(context))
- registry.registerAction(DaemonStatusAction(context))
- registry.registerAction(CancelBuildAction(context))
- registry.registerAction(ProjectSyncAction(context))
+ // Toolbar actions
+ registry.registerAction(UndoAction(context))
+ registry.registerAction(RedoAction(context))
+ registry.registerAction(QuickRunAction(context))
+ registry.registerAction(RunActionMenu(context))
+ registry.registerAction(SaveFileAction(context))
+ registry.registerAction(PreviewLayoutAction(context))
+ registry.registerAction(FindActionMenu(context))
+ registry.registerAction(FileTreeAction(context))
+ registry.registerAction(DaemonStatusAction(context))
+ registry.registerAction(CancelBuildAction(context))
+ registry.registerAction(ProjectSyncAction(context))
- // editor text actions
- registry.registerAction(ExpandSelectionAction(context))
- registry.registerAction(SelectAllAction(context))
- registry.registerAction(CutAction(context))
- registry.registerAction(CopyAction(context))
- registry.registerAction(PasteAction(context))
- registry.registerAction(FormatCodeAction(context))
+ // editor text actions
+ registry.registerAction(ExpandSelectionAction(context))
+ registry.registerAction(SelectAllAction(context))
+ registry.registerAction(CutAction(context))
+ registry.registerAction(CopyAction(context))
+ registry.registerAction(PasteAction(context))
+ registry.registerAction(FormatCodeAction(context))
- // editor search actions
- registry.registerAction(GoToNextAction(context))
- registry.registerAction(GoToPreviousAction(context))
- registry.registerAction(ReplaceAction(context))
- }
-
- @JvmStatic
- fun clear() = ActionsRegistry.getInstance().clearActions(ActionItem.Location.EDITOR_TOOLBAR)
+ // editor search actions
+ registry.registerAction(GoToNextAction(context))
+ registry.registerAction(GoToPreviousAction(context))
+ registry.registerAction(ReplaceAction(context))
}
+
+ @JvmStatic
+ fun clear() = ActionsRegistry.getInstance().clearActions(ActionItem.Location.EDITOR_TOOLBAR)
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/utils/EditorBottomSheetBehavior.java b/app/src/main/java/com/itsaky/androidide/utils/EditorBottomSheetBehavior.java
index ce7919600..843c65b35 100644
--- a/app/src/main/java/com/itsaky/androidide/utils/EditorBottomSheetBehavior.java
+++ b/app/src/main/java/com/itsaky/androidide/utils/EditorBottomSheetBehavior.java
@@ -31,8 +31,8 @@ import com.itsaky.androidide.databinding.LayoutEditorBottomSheetBinding;
public class EditorBottomSheetBehavior extends BottomSheetBehavior {
- private LayoutEditorBottomSheetBinding binding;
private static final ILogger LOG = ILogger.newInstance("EditorBottomSheetBehavior");
+ private LayoutEditorBottomSheetBinding binding;
public EditorBottomSheetBehavior(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
diff --git a/app/src/main/java/com/itsaky/androidide/utils/HighlightRangeHelper.java b/app/src/main/java/com/itsaky/androidide/utils/HighlightRangeHelper.java
index 838f7a9fa..cf47ad57e 100644
--- a/app/src/main/java/com/itsaky/androidide/utils/HighlightRangeHelper.java
+++ b/app/src/main/java/com/itsaky/androidide/utils/HighlightRangeHelper.java
@@ -44,6 +44,7 @@ import java.util.List;
public class HighlightRangeHelper {
+ private static final ILogger LOG = ILogger.newInstance("HighlightRangeHelper");
private final List highlights;
public HighlightRangeHelper(List highlights) {
@@ -54,6 +55,36 @@ public class HighlightRangeHelper {
return isOfKind(line, column, ENUM_TYPE);
}
+ /**
+ * Check if the token at the given index has the given token kind.
+ *
+ * @param line The line to check.
+ * @param column The column to check.
+ * @param kind The kind to check.
+ * @return {@code true} if the token at the given position has the given kind, {@code false}
+ * otherwise.
+ */
+ public boolean isOfKind(int line, int column, HighlightTokenKind kind) {
+ final var position = new Position(line, column);
+ int left = 0;
+ int right = this.highlights.size();
+ int mid;
+ while (left < right) {
+ mid = (left + right) / 2;
+ var token = this.highlights.get(mid);
+ var range = token.getRange();
+ var pos = range.getStart().compareTo(position);
+ if (pos < 0) {
+ left = mid + 1;
+ } else if (pos > 0) {
+ right = mid - 1;
+ } else {
+ return token.getKind() == kind;
+ }
+ }
+ return false;
+ }
+
public boolean isAnnotationType(int line, int column) {
return isOfKind(line, column, ANNOTATION);
}
@@ -121,36 +152,4 @@ public class HighlightRangeHelper {
public boolean isLocal(int line, int column) {
return isOfKind(line, column, LOCAL_VARIABLE);
}
-
- /**
- * Check if the token at the given index has the given token kind.
- *
- * @param line The line to check.
- * @param column The column to check.
- * @param kind The kind to check.
- * @return {@code true} if the token at the given position has the given kind, {@code false}
- * otherwise.
- */
- public boolean isOfKind(int line, int column, HighlightTokenKind kind) {
- final var position = new Position(line, column);
- int left = 0;
- int right = this.highlights.size();
- int mid;
- while (left < right) {
- mid = (left + right) / 2;
- var token = this.highlights.get(mid);
- var range = token.getRange();
- var pos = range.getStart().compareTo(position);
- if (pos < 0) {
- left = mid + 1;
- } else if (pos > 0) {
- right = mid - 1;
- } else {
- return token.getKind() == kind;
- }
- }
- return false;
- }
-
- private static final ILogger LOG = ILogger.newInstance("HighlightRangeHelper");
}
diff --git a/app/src/main/java/com/itsaky/androidide/utils/LSPUtils.java b/app/src/main/java/com/itsaky/androidide/utils/LSPUtils.java
index bd1df4135..7145d2469 100755
--- a/app/src/main/java/com/itsaky/androidide/utils/LSPUtils.java
+++ b/app/src/main/java/com/itsaky/androidide/utils/LSPUtils.java
@@ -19,8 +19,6 @@
**************************************************************************************/
package com.itsaky.androidide.utils;
-import com.itsaky.lsp.models.DiagnosticItem;
-import com.itsaky.lsp.models.DiagnosticSeverity;
import com.itsaky.lsp.models.Position;
import com.itsaky.lsp.models.Range;
@@ -31,19 +29,41 @@ public class LSPUtils {
public static final Position Position_ofZero;
public static final Range Range_ofZero;
+ public static final Comparator RANGE_START_COMPARATOR =
+ (r1, r2) -> {
+ // Check if ranges are null
+ if (r1 == null && r2 != null) {
+ return 1;
+ } else if (r1 != null && r2 == null) {
+ return -1;
+ } else if (r1 == null) {
+ return 0;
+ } else {
+ final int r1StartLine = r1.getStart().getLine();
+ final int r1StartCol = r1.getStart().getColumn();
+ final int r2StartLine = r2.getStart().getLine();
+ final int r2StartCol = r2.getStart().getColumn();
+
+ // Compare by lines
+ if (r1StartLine < r2StartLine) {
+ return -1;
+ } else if (r1StartLine > r2StartLine) {
+ return 1;
+ } else {
+
+ // Lines are same
+ // Compare by columns
+ // Both ranges have same start position
+ return Integer.compare(r1StartCol, r2StartCol);
+ }
+ }
+ };
static {
Position_ofZero = new Position(0, 0);
Range_ofZero = new Range(Position_ofZero, Position_ofZero);
}
- public static boolean isEqual(Position p1, Position p2) {
- if (p1 == null) return false;
- if (p2 == null) return false;
-
- return p1.getLine() == p2.getLine() && p1.getColumn() == p2.getColumn();
- }
-
public static boolean isInRange(Range range, Position position) {
final int line = position.getLine();
final int column = position.getColumn();
@@ -67,6 +87,13 @@ public class LSPUtils {
&& LSPUtils.isEqual(r1.getEnd(), r2.getEnd());
}
+ public static boolean isEqual(Position p1, Position p2) {
+ if (p1 == null) return false;
+ if (p2 == null) return false;
+
+ return p1.getLine() == p2.getLine() && p1.getColumn() == p2.getColumn();
+ }
+
public static Range getSingleLineRange(int line, int column, int length) {
final Range range = new Range();
range.setStart(new Position(line, column));
@@ -102,34 +129,4 @@ public class LSPUtils {
return -1;
}
-
- public static final Comparator RANGE_START_COMPARATOR =
- (r1, r2) -> {
- // Check if ranges are null
- if (r1 == null && r2 != null) {
- return 1;
- } else if (r1 != null && r2 == null) {
- return -1;
- } else if (r1 == null) {
- return 0;
- } else {
- final int r1StartLine = r1.getStart().getLine();
- final int r1StartCol = r1.getStart().getColumn();
- final int r2StartLine = r2.getStart().getLine();
- final int r2StartCol = r2.getStart().getColumn();
-
- // Compare by lines
- if (r1StartLine < r2StartLine) {
- return -1;
- } else if (r1StartLine > r2StartLine) {
- return 1;
- } else {
-
- // Lines are same
- // Compare by columns
- // Both ranges have same start position
- return Integer.compare(r1StartCol, r2StartCol);
- }
- }
- };
}
diff --git a/app/src/main/java/com/itsaky/androidide/utils/ListingFileRedirect.kt b/app/src/main/java/com/itsaky/androidide/utils/ListingFileRedirect.kt
index 5eff140b6..d6e1ea55b 100644
--- a/app/src/main/java/com/itsaky/androidide/utils/ListingFileRedirect.kt
+++ b/app/src/main/java/com/itsaky/androidide/utils/ListingFileRedirect.kt
@@ -23,21 +23,21 @@ import java.util.*
class ListingFileRedirect {
- companion object {
- /** Redirect file will have this marker as the first line as comment. */
- private const val REDIRECT_MARKER = "#- File Locator -"
+ companion object {
+ /** Redirect file will have this marker as the first line as comment. */
+ private const val REDIRECT_MARKER = "#- File Locator -"
- /** Property name in a [Properties] for the metadata file location. */
- private const val REDIRECT_PROPERTY_NAME = "listingFile"
+ /** Property name in a [Properties] for the metadata file location. */
+ private const val REDIRECT_PROPERTY_NAME = "listingFile"
- @JvmStatic
- fun maybeExtractRedirectedFile(redirectFile: File): File? {
- val fileContent = redirectFile.readText()
- return if (fileContent.startsWith(REDIRECT_MARKER)) {
- val fileLocator = Properties().also { it.load(StringReader(fileContent)) }
- val file = File(fileLocator.getProperty(REDIRECT_PROPERTY_NAME))
- if (!file.isAbsolute) redirectFile.parentFile!!.resolve(file) else file
- } else null
- }
+ @JvmStatic
+ fun maybeExtractRedirectedFile(redirectFile: File): File? {
+ val fileContent = redirectFile.readText()
+ return if (fileContent.startsWith(REDIRECT_MARKER)) {
+ val fileLocator = Properties().also { it.load(StringReader(fileContent)) }
+ val file = File(fileLocator.getProperty(REDIRECT_PROPERTY_NAME))
+ if (!file.isAbsolute) redirectFile.parentFile!!.resolve(file) else file
+ } else null
}
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/utils/ProjectWriter.java b/app/src/main/java/com/itsaky/androidide/utils/ProjectWriter.java
index 53b2dd158..62848034e 100755
--- a/app/src/main/java/com/itsaky/androidide/utils/ProjectWriter.java
+++ b/app/src/main/java/com/itsaky/androidide/utils/ProjectWriter.java
@@ -46,8 +46,6 @@ import java.util.zip.ZipInputStream;
public class ProjectWriter {
- private static ProjectWriterCallback callback;
-
private static final String XML_TEMPLATE_PATH = "templates/xml";
private static final String SOURCE_PATH_REGEX = "/.*/src/.*/java|kt";
private static final String FILE_EXT_REGEX = ".*/java|kt|gradle|xml|txt|cpp";
@@ -58,6 +56,7 @@ public class ProjectWriter {
PACKAGE_NAME_CPP = "{$package_name_cpp}",
CPP_FLAGS = "$cpp_flags",
LIBRARY_NAME = "$library_name";
+ private static ProjectWriterCallback callback;
@NonNull
public static String createMenu() {
diff --git a/app/src/main/java/com/itsaky/androidide/utils/Symbols.java b/app/src/main/java/com/itsaky/androidide/utils/Symbols.java
index 452e09966..59845a2a2 100755
--- a/app/src/main/java/com/itsaky/androidide/utils/Symbols.java
+++ b/app/src/main/java/com/itsaky/androidide/utils/Symbols.java
@@ -41,15 +41,6 @@ public class Symbols {
return new Symbol[0];
}
- public static String createTabSpaces() {
- int size = StudioApp.getInstance().getPrefManager().getEditorTabSize();
- StringBuilder tab = new StringBuilder();
- for (int i = 1; i <= size; i++) {
- tab.append(" ");
- }
- return tab.toString();
- }
-
public static Symbol[] javaSymbols() {
return new Symbol[] {
new Symbol("↹", "\t"),
@@ -105,4 +96,13 @@ public class Symbols {
new Symbol("-")
};
}
+
+ public static String createTabSpaces() {
+ int size = StudioApp.getInstance().getPrefManager().getEditorTabSize();
+ StringBuilder tab = new StringBuilder();
+ for (int i = 1; i <= size; i++) {
+ tab.append(" ");
+ }
+ return tab.toString();
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/viewmodel/WizardViewModel.java b/app/src/main/java/com/itsaky/androidide/viewmodel/WizardViewModel.java
index f12e7c5cb..367479b5b 100644
--- a/app/src/main/java/com/itsaky/androidide/viewmodel/WizardViewModel.java
+++ b/app/src/main/java/com/itsaky/androidide/viewmodel/WizardViewModel.java
@@ -8,14 +8,13 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.blankj.utilcode.util.CollectionUtils;
-
import com.itsaky.androidide.R;
import com.itsaky.androidide.interfaces.ProjectWriterCallback;
import com.itsaky.androidide.models.NewProjectDetails;
import com.itsaky.androidide.models.ProjectTemplate;
-
import com.itsaky.androidide.tasks.TaskExecutor;
import com.itsaky.androidide.tasks.callables.ProjectCreatorCallable;
+
import java.io.File;
import java.util.ArrayList;
import java.util.List;
diff --git a/app/src/main/java/com/itsaky/androidide/views/MaterialBanner.java b/app/src/main/java/com/itsaky/androidide/views/MaterialBanner.java
index dd0c8a205..d71c70101 100755
--- a/app/src/main/java/com/itsaky/androidide/views/MaterialBanner.java
+++ b/app/src/main/java/com/itsaky/androidide/views/MaterialBanner.java
@@ -103,17 +103,17 @@ public class MaterialBanner extends CoordinatorLayout {
Animation anim =
new Animation() {
+ @Override
+ public boolean willChangeBounds() {
+ return true;
+ }
+
@Override
public void applyTransformation(float time, Transformation t) {
p.height = time == 1f ? -2 : (int) (height * time);
root.setLayoutParams(p);
root.requestLayout();
}
-
- @Override
- public boolean willChangeBounds() {
- return true;
- }
};
anim.setDuration(200);
@@ -126,6 +126,11 @@ public class MaterialBanner extends CoordinatorLayout {
final int initialHeight = getMeasuredHeight();
Animation animation =
new Animation() {
+ @Override
+ public boolean willChangeBounds() {
+ return true;
+ }
+
@Override
public void applyTransformation(float interpolatedTime, Transformation t) {
if (interpolatedTime == 1f) {
@@ -136,11 +141,6 @@ public class MaterialBanner extends CoordinatorLayout {
root.requestLayout();
}
}
-
- @Override
- public boolean willChangeBounds() {
- return true;
- }
};
animation.setDuration((long) (initialHeight / getResources().getDisplayMetrics().density));
root.startAnimation(animation);
@@ -150,40 +150,40 @@ public class MaterialBanner extends CoordinatorLayout {
return setIcon(ContextCompat.getDrawable(getContext(), icon));
}
- public MaterialBanner setPositive(@StringRes int text, OnPositiveClickListener listener) {
- return setPositive(getContext().getString(text), listener);
- }
-
- public MaterialBanner setNegative(@StringRes int text, OnNegativeClickListener listener) {
- return setNegative(getContext().getString(text), listener);
- }
-
- public MaterialBanner setContentText(@StringRes int text) {
- return setContentText(getContext().getString(text));
- }
-
- public MaterialBanner setContentText(String contentText) {
- this.contentText = contentText;
- return this;
- }
-
public MaterialBanner setIcon(Drawable icon) {
this.iconDrawable = icon;
return this;
}
+ public MaterialBanner setPositive(@StringRes int text, OnPositiveClickListener listener) {
+ return setPositive(getContext().getString(text), listener);
+ }
+
public MaterialBanner setPositive(String text, OnPositiveClickListener listener) {
this.rightButtonText = text;
this.positiveListener = listener;
return this;
}
+ public MaterialBanner setNegative(@StringRes int text, OnNegativeClickListener listener) {
+ return setNegative(getContext().getString(text), listener);
+ }
+
public MaterialBanner setNegative(String text, OnNegativeClickListener listener) {
this.leftButtonText = text;
this.negativeListener = listener;
return this;
}
+ public MaterialBanner setContentText(@StringRes int text) {
+ return setContentText(getContext().getString(text));
+ }
+
+ public MaterialBanner setContentText(String contentText) {
+ this.contentText = contentText;
+ return this;
+ }
+
public MaterialBanner setBannerBackgroundColor(int backgroundColor) {
this.backgroundColor = backgroundColor;
return this;
diff --git a/app/src/main/java/com/itsaky/androidide/views/ScalableTabLayout.kt b/app/src/main/java/com/itsaky/androidide/views/ScalableTabLayout.kt
index 9984988fa..f9a2e2e3c 100644
--- a/app/src/main/java/com/itsaky/androidide/views/ScalableTabLayout.kt
+++ b/app/src/main/java/com/itsaky/androidide/views/ScalableTabLayout.kt
@@ -1,4 +1,4 @@
-package com.itsaky.androidide.views;
+package com.itsaky.androidide.views
import android.content.Context
import android.util.AttributeSet
@@ -7,31 +7,31 @@ import com.google.android.material.tabs.TabLayout
// https://stackoverflow.com/a/65605542
class ScalableTabLayout : TabLayout {
- constructor(context: Context) : super(context)
- constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
- constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
- context,
- attrs,
- defStyleAttr
- )
-
- override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
- val tabLayout = getChildAt(0) as ViewGroup
- val childCount = tabLayout.childCount
- if (childCount > 0) {
- val widthPixels = MeasureSpec.getSize(widthMeasureSpec)
- val tabMinWidth = widthPixels / childCount
- var remainderPixels = widthPixels % childCount
- for (i in 0 until childCount) {
- val it = tabLayout.getChildAt(i)
- if (remainderPixels > 0) {
- it.minimumWidth = tabMinWidth + 1
- remainderPixels--
- } else {
- it.minimumWidth = tabMinWidth
- }
- }
+ constructor(context: Context) : super(context)
+ constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
+ constructor(
+ context: Context,
+ attrs: AttributeSet?,
+ defStyleAttr: Int
+ ) : super(context, attrs, defStyleAttr)
+
+ override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+ val tabLayout = getChildAt(0) as ViewGroup
+ val childCount = tabLayout.childCount
+ if (childCount > 0) {
+ val widthPixels = MeasureSpec.getSize(widthMeasureSpec)
+ val tabMinWidth = widthPixels / childCount
+ var remainderPixels = widthPixels % childCount
+ for (i in 0 until childCount) {
+ val it = tabLayout.getChildAt(i)
+ if (remainderPixels > 0) {
+ it.minimumWidth = tabMinWidth + 1
+ remainderPixels--
+ } else {
+ it.minimumWidth = tabMinWidth
}
- super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+ }
}
-}
\ No newline at end of file
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec)
+ }
+}
diff --git a/app/src/main/java/com/itsaky/androidide/views/SymbolInputView.java b/app/src/main/java/com/itsaky/androidide/views/SymbolInputView.java
index 8d9b6f0dd..86745a856 100755
--- a/app/src/main/java/com/itsaky/androidide/views/SymbolInputView.java
+++ b/app/src/main/java/com/itsaky/androidide/views/SymbolInputView.java
@@ -68,14 +68,14 @@ public class SymbolInputView extends RecyclerView {
this(both, both, offset);
}
- public Symbol(String label, String commit) {
- this(label, commit, 1);
- }
-
public Symbol(String label, String commit, int offset) {
this.label = label;
this.commit = commit;
this.offset = offset;
}
+
+ public Symbol(String label, String commit) {
+ this(label, commit, 1);
+ }
}
}
diff --git a/app/src/main/java/com/itsaky/androidide/views/editor/BaseEditorWindow.java b/app/src/main/java/com/itsaky/androidide/views/editor/BaseEditorWindow.java
index 9d8f7bb39..d72bb8eaa 100644
--- a/app/src/main/java/com/itsaky/androidide/views/editor/BaseEditorWindow.java
+++ b/app/src/main/java/com/itsaky/androidide/views/editor/BaseEditorWindow.java
@@ -83,8 +83,13 @@ public abstract class BaseEditorWindow extends EditorPopupWindow {
return text;
}
- protected View getRootView() {
- return this.text;
+ protected Drawable createBackground() {
+ GradientDrawable background = new GradientDrawable();
+ background.setShape(GradientDrawable.RECTANGLE);
+ background.setColor(0xff212121);
+ background.setStroke(1, 0xffffffff);
+ background.setCornerRadius(8);
+ return background;
}
public void displayWindow() {
@@ -99,13 +104,8 @@ public abstract class BaseEditorWindow extends EditorPopupWindow {
show();
}
- protected Drawable createBackground() {
- GradientDrawable background = new GradientDrawable();
- background.setShape(GradientDrawable.RECTANGLE);
- background.setColor(0xff212121);
- background.setStroke(1, 0xffffffff);
- background.setCornerRadius(8);
- return background;
+ protected View getRootView() {
+ return this.text;
}
@NonNull
diff --git a/app/src/main/java/com/itsaky/androidide/views/editor/CodeEditorView.java b/app/src/main/java/com/itsaky/androidide/views/editor/CodeEditorView.java
index d659924d5..f8feee910 100644
--- a/app/src/main/java/com/itsaky/androidide/views/editor/CodeEditorView.java
+++ b/app/src/main/java/com/itsaky/androidide/views/editor/CodeEditorView.java
@@ -134,6 +134,11 @@ public class CodeEditorView extends FrameLayout {
return bundle;
}
+ @Nullable
+ public File getFile() {
+ return file;
+ }
+
private void handleContentChange(@NonNull ContentChangeEvent event) {
isModified = true;
@@ -157,96 +162,54 @@ public class CodeEditorView extends FrameLayout {
}
}
- public boolean save() {
- final var file = getFile();
- if (file == null) {
- LOG.error("Cannot save file. File instance is null.");
- return false;
- }
-
- if (!isModified() && file.exists()) {
- LOG.info(file.getName());
- LOG.info("File was not modified. Skipping save operation.");
- return false;
- }
-
- final var text = getEditor().getText().toString();
-
+ private void closeCurrentTag(String text, int line, int col) {
try {
- FileUtil.writeFile(file, text);
- notifySaved();
- isModified = false;
- return true;
- } catch (IOException io) {
- LOG.error("Failed to save file", file, io);
- return false;
+ XMLLexer lexer = new XMLLexer(CharStreams.fromReader(new StringReader(text)));
+ Token token;
+ boolean wasSlash = false, wasOpen = false;
+ ArrayList currentNames = new ArrayList<>();
+ while (((token = lexer.nextToken()) != null && token.getType() != token.EOF)) {
+ final int type = token.getType();
+ if (type == XMLLexer.OPEN) {
+ wasOpen = true;
+ } else if (type == XMLLexer.Name) {
+ if (wasOpen && wasSlash && currentNames.size() > 0) {
+ currentNames.remove(0);
+ } else if (wasOpen) {
+ currentNames.add(0, token.getText());
+ wasOpen = false;
+ }
+ } else if (type == XMLLexer.OPEN_SLASH) {
+ int l = token.getLine() - 1;
+ int c = token.getCharPositionInLine();
+ if (l == line && c == col) {
+ break;
+ } else if (currentNames.size() > 0) {
+ currentNames.remove(0);
+ }
+ } else if (type == XMLLexer.SLASH_CLOSE || type == XMLLexer.SPECIAL_CLOSE) {
+ if (currentNames.size() > 0 && token.getText().trim().endsWith("/>")) {
+ currentNames.remove(0);
+ }
+ } else if (type == XMLLexer.SLASH) {
+ wasSlash = true;
+ } else {
+ wasOpen = wasSlash = false;
+ }
+ }
+
+ if (currentNames.size() > 0) {
+ binding.editor.getText().insert(line, col + 2, currentNames.get(0));
+ }
+ } catch (Throwable th) {
+ LOG.error("Unable to close current tag", th);
}
}
- @NonNull
- private List getLines(Content text) {
- final var count = text.getLineCount();
- final var result = new ArrayList();
-
- for (int i = 0; i < count; i++) {
- result.add(text.getLine(i));
- }
-
- return result;
- }
-
public IDEEditor getEditor() {
return binding.editor;
}
- public LayoutCodeEditorBinding getBinding() {
- return binding;
- }
-
- @Nullable
- public File getFile() {
- return file;
- }
-
- public String getText() {
- return binding.editor.getText().toString();
- }
-
- public boolean isModified() {
- return isModified;
- }
-
- public void onPause() {
- // unimplemented
- }
-
- public void onResume() {
- configureEditorIfNeeded();
- }
-
- public void onEditorSelected() {
- final var editor = getEditor();
- if (editor != null) {
- editor.onEditorSelected();
- }
- }
-
- public void undo() {
- if (binding.editor.canUndo()) {
- binding.editor.undo();
- }
- }
-
- public void redo() {
- if (binding.editor.canRedo()) {
- binding.editor.redo();
- }
- }
-
- public void beginSearch() {
- binding.editor.beginSearchMode();
- }
-
protected void postRead() {
binding.editor.setEditorLanguage(createLanguage(file));
binding.editor.setLanguageServer(createLanguageServer(file));
@@ -381,48 +344,34 @@ public class CodeEditorView extends FrameLayout {
isFirstCreate = false;
}
- private void closeCurrentTag(String text, int line, int col) {
- try {
- XMLLexer lexer = new XMLLexer(CharStreams.fromReader(new StringReader(text)));
- Token token;
- boolean wasSlash = false, wasOpen = false;
- ArrayList currentNames = new ArrayList<>();
- while (((token = lexer.nextToken()) != null && token.getType() != token.EOF)) {
- final int type = token.getType();
- if (type == XMLLexer.OPEN) {
- wasOpen = true;
- } else if (type == XMLLexer.Name) {
- if (wasOpen && wasSlash && currentNames.size() > 0) {
- currentNames.remove(0);
- } else if (wasOpen) {
- currentNames.add(0, token.getText());
- wasOpen = false;
- }
- } else if (type == XMLLexer.OPEN_SLASH) {
- int l = token.getLine() - 1;
- int c = token.getCharPositionInLine();
- if (l == line && c == col) {
- break;
- } else if (currentNames.size() > 0) {
- currentNames.remove(0);
- }
- } else if (type == XMLLexer.SLASH_CLOSE || type == XMLLexer.SPECIAL_CLOSE) {
- if (currentNames.size() > 0 && token.getText().trim().endsWith("/>")) {
- currentNames.remove(0);
- }
- } else if (type == XMLLexer.SLASH) {
- wasSlash = true;
- } else {
- wasOpen = wasSlash = false;
- }
- }
-
- if (currentNames.size() > 0) {
- binding.editor.getText().insert(line, col + 2, currentNames.get(0));
- }
- } catch (Throwable th) {
- LOG.error("Unable to close current tag", th);
+ public boolean save() {
+ final var file = getFile();
+ if (file == null) {
+ LOG.error("Cannot save file. File instance is null.");
+ return false;
}
+
+ if (!isModified() && file.exists()) {
+ LOG.info(file.getName());
+ LOG.info("File was not modified. Skipping save operation.");
+ return false;
+ }
+
+ final var text = getEditor().getText().toString();
+
+ try {
+ FileUtil.writeFile(file, text);
+ notifySaved();
+ isModified = false;
+ return true;
+ } catch (IOException io) {
+ LOG.error("Failed to save file", file, io);
+ return false;
+ }
+ }
+
+ public boolean isModified() {
+ return isModified;
}
private void notifySaved() {
@@ -433,9 +382,60 @@ public class CodeEditorView extends FrameLayout {
}
}
+ public LayoutCodeEditorBinding getBinding() {
+ return binding;
+ }
+
+ public String getText() {
+ return binding.editor.getText().toString();
+ }
+
+ public void onPause() {
+ // unimplemented
+ }
+
+ public void onResume() {
+ configureEditorIfNeeded();
+ }
+
+ public void onEditorSelected() {
+ final var editor = getEditor();
+ if (editor != null) {
+ editor.onEditorSelected();
+ }
+ }
+
+ public void undo() {
+ if (binding.editor.canUndo()) {
+ binding.editor.undo();
+ }
+ }
+
+ public void redo() {
+ if (binding.editor.canRedo()) {
+ binding.editor.redo();
+ }
+ }
+
+ public void beginSearch() {
+ binding.editor.beginSearchMode();
+ }
+
/** Mark this files as saved. Even if it not saved. */
public void markAsSaved() {
isModified = false;
notifySaved();
}
+
+ @NonNull
+ private List getLines(Content text) {
+ final var count = text.getLineCount();
+ final var result = new ArrayList();
+
+ for (int i = 0; i < count; i++) {
+ result.add(text.getLine(i));
+ }
+
+ return result;
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/views/editor/IDEEditor.java b/app/src/main/java/com/itsaky/androidide/views/editor/IDEEditor.java
index cb28b7e49..0d422c0f7 100644
--- a/app/src/main/java/com/itsaky/androidide/views/editor/IDEEditor.java
+++ b/app/src/main/java/com/itsaky/androidide/views/editor/IDEEditor.java
@@ -121,49 +121,6 @@ public class IDEEditor extends CodeEditor {
getDiagnosticWindow().showDiagnostic(mLanguageClient.getDiagnosticAt(getFile(), line, column));
}
- /**
- * Notify the language server that the content of this file has been changed.
- *
- * @param event The content change event.
- */
- private void handleContentChange(ContentChangeEvent event, Unsubscribe unsubscribe) {
- if (getFile() == null || mLanguageServer == null) {
- return;
- }
-
- CompletableFuture.runAsync(
- () -> {
- final var documentHandler = mLanguageServer.getDocumentHandler();
- final var file = getFile().toPath();
- if (documentHandler.accepts(file)) {
- documentHandler.onContentChange(
- new DocumentChangeEvent(file, getText(), mFileVersion + 1));
- }
-
- checkForSignatureHelp(event);
- });
- }
-
- public static int createInputFlags() {
- var flags =
- EditorInfo.TYPE_CLASS_TEXT
- | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
- | EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
- if (StudioApp.getInstance()
- .getPrefManager()
- .getBoolean(PreferenceManager.KEY_EDITOR_FLAG_PASSWORD, true)) {
- flags |= EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
- }
-
- return flags;
- }
-
- @Nullable
- private DiagnosticItem binarySearchDiagnostic(
- @NonNull List diagnostics, int line, int column) {
- return DiagnosticUtil.binarySearchDiagnostic(diagnostics, line, column);
- }
-
private DiagnosticWindow getDiagnosticWindow() {
if (mDiagnosticWindow == null) {
mDiagnosticWindow = new DiagnosticWindow(this);
@@ -223,6 +180,29 @@ public class IDEEditor extends CodeEditor {
}
}
+ /**
+ * Notify the language server that the content of this file has been changed.
+ *
+ * @param event The content change event.
+ */
+ private void handleContentChange(ContentChangeEvent event, Unsubscribe unsubscribe) {
+ if (getFile() == null || mLanguageServer == null) {
+ return;
+ }
+
+ CompletableFuture.runAsync(
+ () -> {
+ final var documentHandler = mLanguageServer.getDocumentHandler();
+ final var file = getFile().toPath();
+ if (documentHandler.accepts(file)) {
+ documentHandler.onContentChange(
+ new DocumentChangeEvent(file, getText(), mFileVersion + 1));
+ }
+
+ checkForSignatureHelp(event);
+ });
+ }
+
/**
* Checks if the content change event should trigger signature help. Signature help trigger
* characters are :
@@ -292,6 +272,20 @@ public class IDEEditor extends CodeEditor {
return mSignatureHelpWindow;
}
+ public static int createInputFlags() {
+ var flags =
+ EditorInfo.TYPE_CLASS_TEXT
+ | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE
+ | EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
+ if (StudioApp.getInstance()
+ .getPrefManager()
+ .getBoolean(PreferenceManager.KEY_EDITOR_FLAG_PASSWORD, true)) {
+ flags |= EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
+ }
+
+ return flags;
+ }
+
/**
* Set the selection of this editor to the given position.
*
@@ -506,15 +500,6 @@ public class IDEEditor extends CodeEditor {
}
}
- /**
- * Dismisses the given dialog on the UI thread.
- *
- * @param dialog The dialog to dismiss.
- */
- private void dismissOnUiThread(@NonNull final Dialog dialog) {
- ThreadUtils.runOnUiThread(dialog::dismiss);
- }
-
/**
* Checks if the given range is valid for this editor's text.
*
@@ -570,6 +555,15 @@ public class IDEEditor extends CodeEditor {
return column >= 0 && column < getText().getColumnCount(line);
}
+ /**
+ * Dismisses the given dialog on the UI thread.
+ *
+ * @param dialog The dialog to dismiss.
+ */
+ private void dismissOnUiThread(@NonNull final Dialog dialog) {
+ ThreadUtils.runOnUiThread(dialog::dismiss);
+ }
+
/**
* If any language server instance is set, finds the references to of the token at the current
* cursor position.
@@ -850,4 +844,10 @@ public class IDEEditor extends CodeEditor {
LOG.error("Unable start search action mode. Activity must inherit AppCompatActivity.");
}
}
+
+ @Nullable
+ private DiagnosticItem binarySearchDiagnostic(
+ @NonNull List diagnostics, int line, int column) {
+ return DiagnosticUtil.binarySearchDiagnostic(diagnostics, line, column);
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/views/editor/SearchActionMode.kt b/app/src/main/java/com/itsaky/androidide/views/editor/SearchActionMode.kt
index ef7054fc3..bf3c1b015 100644
--- a/app/src/main/java/com/itsaky/androidide/views/editor/SearchActionMode.kt
+++ b/app/src/main/java/com/itsaky/androidide/views/editor/SearchActionMode.kt
@@ -38,70 +38,70 @@ import io.github.rosemoe.sora.widget.EditorSearcher.SearchOptions
*/
class SearchActionMode(val editor: IDEEditor) : ActionMode.Callback {
- @SuppressLint("RestrictedApi")
- override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
+ @SuppressLint("RestrictedApi")
+ override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
- if (mode == null) {
- return false
- }
-
- if (menu is MenuBuilder) {
- menu.setOptionalIconsVisible(true)
- }
-
- val search = SearchView(editor.context)
- search.setOnQueryTextListener(OnQueryListener(editor))
- search.isIconified = false
- search.queryHint = editor.context.getString(R.string.text_to_search)
- search.performClick()
- search.setIconifiedByDefault(false)
- mode.customView = search
- return true
+ if (mode == null) {
+ return false
}
- override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
- if (mode == null || menu == null) {
- return false
- }
-
- menu.clear()
- val registry = ActionsRegistry.getInstance()
- registry.fillMenu(createData(mode), ActionItem.Location.EDITOR_SEARCH_ACTION_MODE, menu)
-
- return true
+ if (menu is MenuBuilder) {
+ menu.setOptionalIconsVisible(true)
}
- override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
- return true
+ val search = SearchView(editor.context)
+ search.setOnQueryTextListener(OnQueryListener(editor))
+ search.isIconified = false
+ search.queryHint = editor.context.getString(R.string.text_to_search)
+ search.performClick()
+ search.setIconifiedByDefault(false)
+ mode.customView = search
+ return true
+ }
+
+ override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
+ if (mode == null || menu == null) {
+ return false
}
- override fun onDestroyActionMode(mode: ActionMode?) {
+ menu.clear()
+ val registry = ActionsRegistry.getInstance()
+ registry.fillMenu(createData(mode), ActionItem.Location.EDITOR_SEARCH_ACTION_MODE, menu)
+
+ return true
+ }
+
+ override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
+ return true
+ }
+
+ override fun onDestroyActionMode(mode: ActionMode?) {
+ editor.searcher.stopSearch()
+ }
+
+ private fun createData(mode: ActionMode): ActionData {
+ return ActionData().apply {
+ put(Context::class.java, editor.context)
+ put(IDEEditor::class.java, editor)
+ put(CodeEditor::class.java, editor)
+ put(ActionMode::class.java, mode)
+ }
+ }
+
+ private class OnQueryListener(val editor: IDEEditor) : SearchView.OnQueryTextListener {
+ override fun onQueryTextSubmit(query: String?): Boolean {
+ editor.searcher.gotoNext()
+ return false
+ }
+
+ override fun onQueryTextChange(newText: String?): Boolean {
+ if (TextUtils.isEmpty(newText)) {
editor.searcher.stopSearch()
+ return false
+ }
+
+ editor.searcher.search(newText!!, SearchOptions(false, false))
+ return false
}
-
- private fun createData(mode: ActionMode): ActionData {
- return ActionData().apply {
- put(Context::class.java, editor.context)
- put(IDEEditor::class.java, editor)
- put(CodeEditor::class.java, editor)
- put(ActionMode::class.java, mode)
- }
- }
-
- private class OnQueryListener(val editor: IDEEditor) : SearchView.OnQueryTextListener {
- override fun onQueryTextSubmit(query: String?): Boolean {
- editor.searcher.gotoNext()
- return false
- }
-
- override fun onQueryTextChange(newText: String?): Boolean {
- if (TextUtils.isEmpty(newText)) {
- editor.searcher.stopSearch()
- return false
- }
-
- editor.searcher.search(newText!!, SearchOptions(false, false))
- return false
- }
- }
+ }
}
diff --git a/app/src/main/java/com/itsaky/androidide/views/transition/CubicBezierArc.java b/app/src/main/java/com/itsaky/androidide/views/transition/CubicBezierArc.java
index dc49823b4..d2f3a3a81 100755
--- a/app/src/main/java/com/itsaky/androidide/views/transition/CubicBezierArc.java
+++ b/app/src/main/java/com/itsaky/androidide/views/transition/CubicBezierArc.java
@@ -57,6 +57,58 @@ public class CubicBezierArc {
calculateControlPoints(angle, start, end);
}
+ private void calculateControlPoints(float angle, Point start, Point end) {
+ double angleRadians = Math.toRadians(angle);
+
+ float deltaX = start.x - end.x;
+ float deltaY = start.y - end.y;
+ float halfChordLength = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY) / 2;
+ float radius = halfChordLength / (float) Math.sin(angleRadians / 2.0f);
+ // The length of the line from the start or end point to the control point
+ float controlLength = (float) ((4f / 3f) * Math.tan(angleRadians / 4)) * radius;
+
+ float angleToControl = (float) Math.toDegrees(Math.atan(controlLength / radius));
+
+ // The mid point of the line from start to end
+ Point midPointChord = new Point((start.x + end.x) / 2, (start.y + end.y) / 2);
+
+ // Angle between line from circle centre to control point, and line between control points
+ float chordRadiusAngle = 180 - 90 - (angle / 2);
+
+ Point center = getTrianglePoint(chordRadiusAngle, midPointChord, end);
+ controlPoint2 = getTrianglePoint(angleToControl, end, center);
+ controlPoint1 = getReflectedPointAboutLine(center, midPointChord, controlPoint2);
+
+ // Get reflected control points
+ reflectedControlPoint1 = getReflectedPointAboutLine(start, end, controlPoint1);
+ reflectedControlPoint2 = getReflectedPointAboutLine(start, end, controlPoint2);
+ }
+
+ private Point getTrianglePoint(float angle, Point a, Point b) {
+ double angleRadians = Math.toRadians(angle);
+ Point thirdPoint = new Point();
+ thirdPoint.x = (float) Math.tan(angleRadians) * (b.y - a.y) * -1;
+ thirdPoint.y = (float) Math.tan(angleRadians) * (b.x - a.x);
+ thirdPoint.x = thirdPoint.x + a.x;
+ thirdPoint.y = thirdPoint.y + a.y;
+ return thirdPoint;
+ }
+
+ private Point getReflectedPointAboutLine(Point start, Point end, Point reflect) {
+ Point reflectedPoint = new Point();
+ if (start.x != end.x) {
+ float m = (start.y - end.y) / (start.x - end.x);
+ float c = end.y - (m * end.x);
+ float d = (reflect.x + (reflect.y - c) * m) / (1 + (m * m));
+ reflectedPoint.x = (2 * d) - reflect.x;
+ reflectedPoint.y = (2 * d * m) - reflect.y + (2 * c);
+ } else {
+ reflectedPoint.y = reflect.y;
+ reflectedPoint.x = start.x - (reflect.x - start.x);
+ }
+ return reflectedPoint;
+ }
+
/**
* Returns the start point
*
@@ -122,56 +174,4 @@ public class CubicBezierArc {
this.y = y;
}
}
-
- private Point getTrianglePoint(float angle, Point a, Point b) {
- double angleRadians = Math.toRadians(angle);
- Point thirdPoint = new Point();
- thirdPoint.x = (float) Math.tan(angleRadians) * (b.y - a.y) * -1;
- thirdPoint.y = (float) Math.tan(angleRadians) * (b.x - a.x);
- thirdPoint.x = thirdPoint.x + a.x;
- thirdPoint.y = thirdPoint.y + a.y;
- return thirdPoint;
- }
-
- private Point getReflectedPointAboutLine(Point start, Point end, Point reflect) {
- Point reflectedPoint = new Point();
- if (start.x != end.x) {
- float m = (start.y - end.y) / (start.x - end.x);
- float c = end.y - (m * end.x);
- float d = (reflect.x + (reflect.y - c) * m) / (1 + (m * m));
- reflectedPoint.x = (2 * d) - reflect.x;
- reflectedPoint.y = (2 * d * m) - reflect.y + (2 * c);
- } else {
- reflectedPoint.y = reflect.y;
- reflectedPoint.x = start.x - (reflect.x - start.x);
- }
- return reflectedPoint;
- }
-
- private void calculateControlPoints(float angle, Point start, Point end) {
- double angleRadians = Math.toRadians(angle);
-
- float deltaX = start.x - end.x;
- float deltaY = start.y - end.y;
- float halfChordLength = (float) Math.sqrt(deltaX * deltaX + deltaY * deltaY) / 2;
- float radius = halfChordLength / (float) Math.sin(angleRadians / 2.0f);
- // The length of the line from the start or end point to the control point
- float controlLength = (float) ((4f / 3f) * Math.tan(angleRadians / 4)) * radius;
-
- float angleToControl = (float) Math.toDegrees(Math.atan(controlLength / radius));
-
- // The mid point of the line from start to end
- Point midPointChord = new Point((start.x + end.x) / 2, (start.y + end.y) / 2);
-
- // Angle between line from circle centre to control point, and line between control points
- float chordRadiusAngle = 180 - 90 - (angle / 2);
-
- Point center = getTrianglePoint(chordRadiusAngle, midPointChord, end);
- controlPoint2 = getTrianglePoint(angleToControl, end, center);
- controlPoint1 = getReflectedPointAboutLine(center, midPointChord, controlPoint2);
-
- // Get reflected control points
- reflectedControlPoint1 = getReflectedPointAboutLine(start, end, controlPoint1);
- reflectedControlPoint2 = getReflectedPointAboutLine(start, end, controlPoint2);
- }
}
diff --git a/app/src/main/java/com/itsaky/androidide/views/transition/ProgressTransition.java b/app/src/main/java/com/itsaky/androidide/views/transition/ProgressTransition.java
index a87bece50..3890bbde7 100755
--- a/app/src/main/java/com/itsaky/androidide/views/transition/ProgressTransition.java
+++ b/app/src/main/java/com/itsaky/androidide/views/transition/ProgressTransition.java
@@ -45,6 +45,21 @@ public class ProgressTransition extends Transition {
}
};
+ @Override
+ public Animator createAnimator(
+ ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) {
+ if (startValues != null && endValues != null && endValues.view instanceof ProgressBar) {
+ ProgressBar progressBar = (ProgressBar) endValues.view;
+ int start = (Integer) startValues.values.get(PROPNAME_PROGRESS);
+ int end = (Integer) endValues.values.get(PROPNAME_PROGRESS);
+ if (start != end) {
+ progressBar.setProgress(start);
+ return ObjectAnimator.ofInt(progressBar, PROGRESS_PROPERTY, end);
+ }
+ }
+ return null;
+ }
+
@Override
public void captureStartValues(TransitionValues transitionValues) {
captureValues(transitionValues);
@@ -61,19 +76,4 @@ public class ProgressTransition extends Transition {
transitionValues.values.put(PROPNAME_PROGRESS, progressBar.getProgress());
}
}
-
- @Override
- public Animator createAnimator(
- ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) {
- if (startValues != null && endValues != null && endValues.view instanceof ProgressBar) {
- ProgressBar progressBar = (ProgressBar) endValues.view;
- int start = (Integer) startValues.values.get(PROPNAME_PROGRESS);
- int end = (Integer) endValues.values.get(PROPNAME_PROGRESS);
- if (start != end) {
- progressBar.setProgress(start);
- return ObjectAnimator.ofInt(progressBar, PROGRESS_PROPERTY, end);
- }
- }
- return null;
- }
}
diff --git a/app/src/main/java/io/github/rosemoe/sora/widget/IDEEditorSearcher.kt b/app/src/main/java/io/github/rosemoe/sora/widget/IDEEditorSearcher.kt
index 3984f26e4..13b0b7f91 100644
--- a/app/src/main/java/io/github/rosemoe/sora/widget/IDEEditorSearcher.kt
+++ b/app/src/main/java/io/github/rosemoe/sora/widget/IDEEditorSearcher.kt
@@ -36,82 +36,84 @@ import java.util.concurrent.*
*/
open class IDEEditorSearcher(editor: IDEEditor) : EditorSearcher(editor) {
- private val log = ILogger.newInstance(javaClass.simpleName)
+ private val log = ILogger.newInstance(javaClass.simpleName)
- protected fun getEditor(): CodeEditor {
- try {
- val field = EditorSearcher::class.java.getDeclaredField("mEditor")
- field.isAccessible = true
- return field.get(this) as CodeEditor
- } catch (error: Throwable) {
- throw RuntimeException("Unable get instance of editor", error)
- }
+ protected fun getEditor(): CodeEditor {
+ try {
+ val field = EditorSearcher::class.java.getDeclaredField("mEditor")
+ field.isAccessible = true
+ return field.get(this) as CodeEditor
+ } catch (error: Throwable) {
+ throw RuntimeException("Unable get instance of editor", error)
+ }
+ }
+
+ fun replaceAllAsync(replacement: String): CompletableFuture {
+ val dialog =
+ ProgressDialog.show(
+ getEditor().context,
+ getEditor().context.getString(string.replaceAll),
+ getEditor().context.getString(string.msg_replacing),
+ true,
+ false
+ )
+ return CompletableFuture.runAsync { replaceAll(replacement) }
+ .thenAccept { getEditor().post { dialog.dismiss() } }
+ }
+
+ override fun replaceAll(replacement: String) {
+ checkState()
+ if (!isResultValid) {
+ Toast.makeText(getEditor().context, "Editor is still preparing", Toast.LENGTH_SHORT).show()
+ return
}
- fun replaceAllAsync(replacement: String): CompletableFuture {
- val dialog =
- ProgressDialog.show(
- getEditor().context,
- getEditor().context.getString(string.replaceAll),
- getEditor().context.getString(string.msg_replacing),
- true,
- false)
- return CompletableFuture.runAsync { replaceAll(replacement) }.thenAccept {
- getEditor().post { dialog.dismiss() }
+ val res = mLastResults
+ try {
+ val sb = getEditor().text.toStringBuilder()
+ val newLength = replacement.length
+ if (mOptions.useRegex) {
+ var delta = 0
+ for (i in 0 until res.size()) {
+ val region = res[i]
+ val start = IntPair.getFirst(region)
+ val end = IntPair.getSecond(region)
+ val oldLength = end - start
+ sb.replace(start + delta, end + delta, replacement)
+ delta += newLength - oldLength
}
- }
-
- override fun replaceAll(replacement: String) {
- checkState()
- if (!isResultValid) {
- Toast.makeText(getEditor().context, "Editor is still preparing", Toast.LENGTH_SHORT)
- .show()
- return
- }
-
- val res = mLastResults
- try {
- val sb = getEditor().text.toStringBuilder()
- val newLength = replacement.length
- if (mOptions.useRegex) {
- var delta = 0
- for (i in 0 until res.size()) {
- val region = res[i]
- val start = IntPair.getFirst(region)
- val end = IntPair.getSecond(region)
- val oldLength = end - start
- sb.replace(start + delta, end + delta, replacement)
- delta += newLength - oldLength
- }
- } else {
- var fromIndex = 0
- var foundIndex: Int
- while (TextUtils.indexOf(sb, mPattern, mOptions.ignoreCase, fromIndex).also {
- foundIndex = it
- } != -1) {
- sb.replace(foundIndex, foundIndex + mPattern.length, replacement)
- fromIndex = foundIndex + newLength
- }
- }
- getEditor().post {
- val pos = getEditor().cursor.left()
- // stopSearch();
- getEditor()
- .text
- .replace(
- 0,
- 0,
- getEditor().lineCount - 1,
- getEditor().text.getColumnCount(getEditor().lineCount - 1),
- sb)
- getEditor().setSelectionAround(pos.line, pos.column)
- }
- } catch (e: Exception) {
- log.error("Failed to replace", e)
+ } else {
+ var fromIndex = 0
+ var foundIndex: Int
+ while (
+ TextUtils.indexOf(sb, mPattern, mOptions.ignoreCase, fromIndex).also {
+ foundIndex = it
+ } != -1
+ ) {
+ sb.replace(foundIndex, foundIndex + mPattern.length, replacement)
+ fromIndex = foundIndex + newLength
}
+ }
+ getEditor().post {
+ val pos = getEditor().cursor.left()
+ // stopSearch();
+ getEditor()
+ .text
+ .replace(
+ 0,
+ 0,
+ getEditor().lineCount - 1,
+ getEditor().text.getColumnCount(getEditor().lineCount - 1),
+ sb
+ )
+ getEditor().setSelectionAround(pos.line, pos.column)
+ }
+ } catch (e: Exception) {
+ log.error("Failed to replace", e)
}
+ }
- private fun checkState() {
- check(hasQuery()) { "pattern not set" }
- }
+ private fun checkState() {
+ check(hasQuery()) { "pattern not set" }
+ }
}
diff --git a/app/src/main/res/anim/popup_in.xml b/app/src/main/res/anim/popup_in.xml
index b5ffae7db..13a57039c 100755
--- a/app/src/main/res/anim/popup_in.xml
+++ b/app/src/main/res/anim/popup_in.xml
@@ -1,19 +1,19 @@
-
+
-
+ android:fromAlpha="0.0"
+ android:interpolator="@android:anim/accelerate_interpolator"
+ android:repeatCount="0"
+ android:toAlpha="1.0" />
-
+
diff --git a/app/src/main/res/anim/popup_out.xml b/app/src/main/res/anim/popup_out.xml
index 37bf78b05..91e6b41bc 100755
--- a/app/src/main/res/anim/popup_out.xml
+++ b/app/src/main/res/anim/popup_out.xml
@@ -1,19 +1,19 @@
-
+
-
+ android:fromAlpha="1.0"
+ android:interpolator="@android:anim/accelerate_interpolator"
+ android:repeatCount="0"
+ android:toAlpha="0.0" />
-
+
diff --git a/app/src/main/res/animator/dialog_in.xml b/app/src/main/res/animator/dialog_in.xml
index c83bedc4c..98ee6726d 100755
--- a/app/src/main/res/animator/dialog_in.xml
+++ b/app/src/main/res/animator/dialog_in.xml
@@ -1,13 +1,13 @@
-
-
+
+
diff --git a/app/src/main/res/animator/dialog_out.xml b/app/src/main/res/animator/dialog_out.xml
index 526c9ce9a..55f7c5164 100755
--- a/app/src/main/res/animator/dialog_out.xml
+++ b/app/src/main/res/animator/dialog_out.xml
@@ -1,13 +1,13 @@
-
-
+
+
diff --git a/app/src/main/res/drawable-xhdpi/ic_font_ligatures.xml b/app/src/main/res/drawable-xhdpi/ic_font_ligatures.xml
index 08912b137..b990c7e64 100644
--- a/app/src/main/res/drawable-xhdpi/ic_font_ligatures.xml
+++ b/app/src/main/res/drawable-xhdpi/ic_font_ligatures.xml
@@ -1,8 +1,10 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/bg_design_container_background.xml b/app/src/main/res/drawable/bg_design_container_background.xml
index df80c8860..c1d6ec620 100755
--- a/app/src/main/res/drawable/bg_design_container_background.xml
+++ b/app/src/main/res/drawable/bg_design_container_background.xml
@@ -1,5 +1,4 @@
-
-
-
+
-
-
-
-
+
+
+
-
-
-
+
+
diff --git a/app/src/main/res/drawable/bg_shadow.xml b/app/src/main/res/drawable/bg_shadow.xml
index 53576c272..b4f13e508 100755
--- a/app/src/main/res/drawable/bg_shadow.xml
+++ b/app/src/main/res/drawable/bg_shadow.xml
@@ -1,14 +1,12 @@
-
- -
-
-
-
-
+
+ -
+
+
+
+
diff --git a/app/src/main/res/drawable/bg_widget_drag_placeholder.xml b/app/src/main/res/drawable/bg_widget_drag_placeholder.xml
index 35c68f3b8..9749b261b 100755
--- a/app/src/main/res/drawable/bg_widget_drag_placeholder.xml
+++ b/app/src/main/res/drawable/bg_widget_drag_placeholder.xml
@@ -1,5 +1,4 @@
-
-
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_file_copy_path.xml b/app/src/main/res/drawable/ic_file_copy_path.xml
index 23ce17bb4..dd9c85f76 100755
--- a/app/src/main/res/drawable/ic_file_copy_path.xml
+++ b/app/src/main/res/drawable/ic_file_copy_path.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M19,21H8V7H19M19,5H8A2,2 0,0 0,6 7V21A2,2 0,0 0,8 23H19A2,2 0,0 0,21 21V7A2,2 0,0 0,19 5M16,1H4A2,2 0,0 0,2 3V17H4V3H16V1Z" />
diff --git a/app/src/main/res/drawable/ic_file_rename.xml b/app/src/main/res/drawable/ic_file_rename.xml
index 5629e285c..17d23e7bd 100755
--- a/app/src/main/res/drawable/ic_file_rename.xml
+++ b/app/src/main/res/drawable/ic_file_rename.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M14.06,9L15,9.94L5.92,19H5V18.08L14.06,9M17.66,3C17.41,3 17.15,3.1 16.96,3.29L15.13,5.12L18.88,8.87L20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18.17,3.09 17.92,3 17.66,3M14.06,6.19L3,17.25V21H6.75L17.81,9.94L14.06,6.19Z" />
diff --git a/app/src/main/res/drawable/ic_file_unknown.xml b/app/src/main/res/drawable/ic_file_unknown.xml
index bf2460d1b..478ca48da 100755
--- a/app/src/main/res/drawable/ic_file_unknown.xml
+++ b/app/src/main/res/drawable/ic_file_unknown.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M14,2H6A2,2 0,0 0,4 4V20A2,2 0,0 0,6 22H18A2,2 0,0 0,20 20V8L14,2M18,20H6V4H13V9H18V20Z" />
diff --git a/app/src/main/res/drawable/ic_filetype_activity.xml b/app/src/main/res/drawable/ic_filetype_activity.xml
index 43b1cd9a5..212025f66 100755
--- a/app/src/main/res/drawable/ic_filetype_activity.xml
+++ b/app/src/main/res/drawable/ic_filetype_activity.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M7,1A2,2 0,0 0,5 3V21A2,2 0,0 0,7 23H17A2,2 0,0 0,19 21V3A2,2 0,0 0,17 1H7M7,4H17V20H7V4M9,6V10H10.5V7.5H13V6H9M13.5,14V16.5H11V18H15V14H13.5Z" />
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_filetype_enum.xml b/app/src/main/res/drawable/ic_filetype_enum.xml
index fbbdcc459..08ba15c8f 100755
--- a/app/src/main/res/drawable/ic_filetype_enum.xml
+++ b/app/src/main/res/drawable/ic_filetype_enum.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M3,5A2,2 0,0 1,5 3H19A2,2 0,0 1,21 5V19A2,2 0,0 1,19 21H5C3.89,21 3,20.1 3,19V5M6,6V18H10V16H8V8H10V6H6M16,16H14V18H18V6H14V8H16V16Z" />
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_filetype_interface.xml b/app/src/main/res/drawable/ic_filetype_interface.xml
index e60b0df80..cc2374d67 100755
--- a/app/src/main/res/drawable/ic_filetype_interface.xml
+++ b/app/src/main/res/drawable/ic_filetype_interface.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M10.59,13.41C11,13.8 11,14.44 10.59,14.83C10.2,15.22 9.56,15.22 9.17,14.83C7.22,12.88 7.22,9.71 9.17,7.76V7.76L12.71,4.22C14.66,2.27 17.83,2.27 19.78,4.22C21.73,6.17 21.73,9.34 19.78,11.29L18.29,12.78C18.3,11.96 18.17,11.14 17.89,10.36L18.36,9.88C19.54,8.71 19.54,6.81 18.36,5.64C17.19,4.46 15.29,4.46 14.12,5.64L10.59,9.17C9.41,10.34 9.41,12.24 10.59,13.41M13.41,9.17C13.8,8.78 14.44,8.78 14.83,9.17C16.78,11.12 16.78,14.29 14.83,16.24V16.24L11.29,19.78C9.34,21.73 6.17,21.73 4.22,19.78C2.27,17.83 2.27,14.66 4.22,12.71L5.71,11.22C5.7,12.04 5.83,12.86 6.11,13.65L5.64,14.12C4.46,15.29 4.46,17.19 5.64,18.36C6.81,19.54 8.71,19.54 9.88,18.36L13.41,14.83C14.59,13.66 14.59,11.76 13.41,10.59C13,10.2 13,9.56 13.41,9.17Z" />
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_filter.xml b/app/src/main/res/drawable/ic_filter.xml
index dba631d07..b5a662cbf 100755
--- a/app/src/main/res/drawable/ic_filter.xml
+++ b/app/src/main/res/drawable/ic_filter.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M15,19.88C15.04,20.18 14.94,20.5 14.71,20.71C14.32,21.1 13.69,21.1 13.3,20.71L9.29,16.7C9.06,16.47 8.96,16.16 9,15.87V10.75L4.21,4.62C3.87,4.19 3.95,3.56 4.38,3.22C4.57,3.08 4.78,3 5,3V3H19V3C19.22,3 19.43,3.08 19.62,3.22C20.05,3.56 20.13,4.19 19.79,4.62L15,10.75V19.88M7.04,5L11,10.06V15.58L13,17.58V10.05L16.96,5H7.04Z" />
diff --git a/app/src/main/res/drawable/ic_folder.xml b/app/src/main/res/drawable/ic_folder.xml
index ac60509e4..569b8c858 100755
--- a/app/src/main/res/drawable/ic_folder.xml
+++ b/app/src/main/res/drawable/ic_folder.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M10,4H4C2.89,4 2,4.89 2,6V18A2,2 0,0 0,4 20H20A2,2 0,0 0,22 18V8C22,6.89 21.1,6 20,6H12L10,4Z" />
diff --git a/app/src/main/res/drawable/ic_format_code.xml b/app/src/main/res/drawable/ic_format_code.xml
index f60369d77..7f9cf7194 100644
--- a/app/src/main/res/drawable/ic_format_code.xml
+++ b/app/src/main/res/drawable/ic_format_code.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_github.xml b/app/src/main/res/drawable/ic_github.xml
index 2068fb5d1..656a49146 100644
--- a/app/src/main/res/drawable/ic_github.xml
+++ b/app/src/main/res/drawable/ic_github.xml
@@ -1,5 +1,4 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_help.xml b/app/src/main/res/drawable/ic_help.xml
index 7b898d20a..ef3fca908 100755
--- a/app/src/main/res/drawable/ic_help.xml
+++ b/app/src/main/res/drawable/ic_help.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M11,18H13V16H11V18M12,2A10,10 0,0 0,2 12A10,10 0,0 0,12 22A10,10 0,0 0,22 12A10,10 0,0 0,12 2M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,6A4,4 0,0 0,8 10H10A2,2 0,0 1,12 8A2,2 0,0 1,14 10C14,12 11,11.75 11,15H13C13,12.75 16,12.5 16,10A4,4 0,0 0,12 6Z" />
diff --git a/app/src/main/res/drawable/ic_hexadecimal.xml b/app/src/main/res/drawable/ic_hexadecimal.xml
index 0889d6d78..56f47b1f9 100755
--- a/app/src/main/res/drawable/ic_hexadecimal.xml
+++ b/app/src/main/res/drawable/ic_hexadecimal.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M7,7C5.9,7 5,7.9 5,9V15C5,16.11 5.9,17 7,17H9C10.11,17 11,16.11 11,15V9C11,7.9 10.11,7 9,7H7M7,9H9V15H7V9M17.6,17L15.5,14.9L13.4,17L12,15.6L14.1,13.5L12,11.4L13.4,10L15.5,12.1L17.6,10L19,11.4L16.9,13.5L19,15.6L17.6,17Z" />
diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml
index 66773f0fb..036c14c32 100755
--- a/app/src/main/res/drawable/ic_info.xml
+++ b/app/src/main/res/drawable/ic_info.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0,0 0,2 12A10,10 0,0 0,12 22A10,10 0,0 0,22 12A10,10 0,0 0,12 2M11,17H13V11H11V17Z" />
diff --git a/app/src/main/res/drawable/ic_language_gradle.xml b/app/src/main/res/drawable/ic_language_gradle.xml
index a6c24b57b..817d0057e 100755
--- a/app/src/main/res/drawable/ic_language_gradle.xml
+++ b/app/src/main/res/drawable/ic_language_gradle.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M6,2C4.89,2 4,2.9 4,4V20C4,21.11 4.89,22 6,22H12V20H6V4H13V9H18V12H20V8L14,2M18,14C17.87,14 17.76,14.09 17.74,14.21L17.55,15.53C17.25,15.66 16.96,15.82 16.7,16L15.46,15.5C15.35,15.5 15.22,15.5 15.15,15.63L14.15,17.36C14.09,17.47 14.11,17.6 14.21,17.68L15.27,18.5C15.25,18.67 15.24,18.83 15.24,19C15.24,19.17 15.25,19.33 15.27,19.5L14.21,20.32C14.12,20.4 14.09,20.53 14.15,20.64L15.15,22.37C15.21,22.5 15.34,22.5 15.46,22.5L16.7,22C16.96,22.18 17.24,22.35 17.55,22.47L17.74,23.79C17.76,23.91 17.86,24 18,24H20C20.11,24 20.22,23.91 20.24,23.79L20.43,22.47C20.73,22.34 21,22.18 21.27,22L22.5,22.5C22.63,22.5 22.76,22.5 22.83,22.37L23.83,20.64C23.89,20.53 23.86,20.4 23.77,20.32L22.7,19.5C22.72,19.33 22.74,19.17 22.74,19C22.74,18.83 22.73,18.67 22.7,18.5L23.76,17.68C23.85,17.6 23.88,17.47 23.82,17.36L22.82,15.63C22.76,15.5 22.63,15.5 22.5,15.5L21.27,16C21,15.82 20.73,15.65 20.42,15.53L20.23,14.21C20.22,14.09 20.11,14 20,14M19,17.5C19.83,17.5 20.5,18.17 20.5,19C20.5,19.83 19.83,20.5 19,20.5C18.16,20.5 17.5,19.83 17.5,19C17.5,18.17 18.17,17.5 19,17.5Z" />
diff --git a/app/src/main/res/drawable/ic_language_java.xml b/app/src/main/res/drawable/ic_language_java.xml
index 3df377479..71fb21890 100755
--- a/app/src/main/res/drawable/ic_language_java.xml
+++ b/app/src/main/res/drawable/ic_language_java.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M16.5,6.08C16.5,6.08 9.66,7.79 12.94,11.56C13.91,12.67 12.69,13.67 12.69,13.67C12.69,13.67 15.14,12.42 14,10.82C12.94,9.35 12.14,8.62 16.5,6.08M12.03,7.28C16.08,4.08 14,2 14,2C14.84,5.3 11.04,6.3 9.67,8.36C8.73,9.76 10.13,11.27 12,13C11.29,11.3 8.78,9.84 12.03,7.28M9.37,17.47C6.29,18.33 11.25,20.1 15.16,18.43C14.78,18.28 14.41,18.1 14.06,17.89C12.7,18.2 11.3,18.26 9.92,18.07C8.61,17.91 9.37,17.47 9.37,17.47M14.69,15.79C12.94,16.17 11.13,16.26 9.35,16.05C8.04,15.92 8.9,15.28 8.9,15.28C5.5,16.41 10.78,17.68 15.5,16.3C15.21,16.19 14.93,16 14.69,15.79M18.11,19.09C18.11,19.09 18.68,19.56 17.5,19.92C15.22,20.6 8.07,20.81 6.09,19.95C5.38,19.64 6.72,19.21 7.14,19.12C7.37,19.06 7.6,19.04 7.83,19.04C7.04,18.5 2.7,20.14 5.64,20.6C13.61,21.9 20.18,20 18.11,19.09M15.37,14.23C15.66,14.04 15.97,13.88 16.29,13.74C16.29,13.74 14.78,14 13.27,14.14C11.67,14.3 10.06,14.32 8.46,14.2C6.11,13.89 9.75,13 9.75,13C8.65,13 7.57,13.26 6.59,13.75C4.54,14.75 11.69,15.2 15.37,14.23M16.27,16.65C16.25,16.69 16.23,16.72 16.19,16.75C21.2,15.44 19.36,12.11 16.96,12.94C16.83,13 16.72,13.08 16.65,13.19C16.79,13.14 16.93,13.1 17.08,13.07C18.28,12.83 20,14.7 16.27,16.65M16.4,21.26C13.39,21.78 10.31,21.82 7.28,21.4C7.28,21.4 7.74,21.78 10.09,21.93C13.69,22.16 19.22,21.8 19.35,20.1C19.38,20.11 19.12,20.75 16.4,21.26Z" />
diff --git a/app/src/main/res/drawable/ic_language_json.xml b/app/src/main/res/drawable/ic_language_json.xml
index 6791c9f87..05869f0b0 100755
--- a/app/src/main/res/drawable/ic_language_json.xml
+++ b/app/src/main/res/drawable/ic_language_json.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M5,3H7V5H5V10A2,2 0,0 1,3 12A2,2 0,0 1,5 14V19H7V21H5C3.93,20.73 3,20.1 3,19V15A2,2 0,0 0,1 13H0V11H1A2,2 0,0 0,3 9V5A2,2 0,0 1,5 3M19,3A2,2 0,0 1,21 5V9A2,2 0,0 0,23 11H24V13H23A2,2 0,0 0,21 15V19A2,2 0,0 1,19 21H17V19H19V14A2,2 0,0 1,21 12A2,2 0,0 1,19 10V5H17V3H19M12,15A1,1 0,0 1,13 16A1,1 0,0 1,12 17A1,1 0,0 1,11 16A1,1 0,0 1,12 15M8,15A1,1 0,0 1,9 16A1,1 0,0 1,8 17A1,1 0,0 1,7 16A1,1 0,0 1,8 15M16,15A1,1 0,0 1,17 16A1,1 0,0 1,16 17A1,1 0,0 1,15 16A1,1 0,0 1,16 15Z" />
diff --git a/app/src/main/res/drawable/ic_language_kotlin.xml b/app/src/main/res/drawable/ic_language_kotlin.xml
index d82087271..ef868cecf 100755
--- a/app/src/main/res/drawable/ic_language_kotlin.xml
+++ b/app/src/main/res/drawable/ic_language_kotlin.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M2,2H22L12,12L22,22H2Z" />
diff --git a/app/src/main/res/drawable/ic_language_xml.xml b/app/src/main/res/drawable/ic_language_xml.xml
index adb411f2c..c8e209525 100755
--- a/app/src/main/res/drawable/ic_language_xml.xml
+++ b/app/src/main/res/drawable/ic_language_xml.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M12.89,3L14.85,3.4L11.11,21L9.15,20.6L12.89,3M19.59,12L16,8.41V5.58L22.42,12L16,18.41V15.58L19.59,12M1.58,12L8,5.58V8.41L4.41,12L8,15.58V18.41L1.58,12Z" />
diff --git a/app/src/main/res/drawable/ic_lint.xml b/app/src/main/res/drawable/ic_lint.xml
index 2a0a6efc1..2285c2abd 100755
--- a/app/src/main/res/drawable/ic_lint.xml
+++ b/app/src/main/res/drawable/ic_lint.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M6.59,3.41L2,8L6.59,12.6L8,11.18L4.82,8L8,4.82L6.59,3.41M12.41,3.41L11,4.82L14.18,8L11,11.18L12.41,12.6L17,8L12.41,3.41M21.59,11.59L13.5,19.68L9.83,16L8.42,17.41L13.5,22.5L23,13L21.59,11.59Z" />
diff --git a/app/src/main/res/drawable/ic_loupe.xml b/app/src/main/res/drawable/ic_loupe.xml
index 1e7c1cb67..166f15ae4 100644
--- a/app/src/main/res/drawable/ic_loupe.xml
+++ b/app/src/main/res/drawable/ic_loupe.xml
@@ -3,7 +3,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
-
+
diff --git a/app/src/main/res/drawable/ic_min_sdk.xml b/app/src/main/res/drawable/ic_min_sdk.xml
index 05058c6c4..d7964bc21 100755
--- a/app/src/main/res/drawable/ic_min_sdk.xml
+++ b/app/src/main/res/drawable/ic_min_sdk.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M6.5,2.27L20,10.14L6.5,18L5.5,16.27L16.03,10.14L5.5,4L6.5,2.27M20,20V22H5V20H20Z" />
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_new_file.xml b/app/src/main/res/drawable/ic_new_file.xml
index 4923032da..02dff1d78 100755
--- a/app/src/main/res/drawable/ic_new_file.xml
+++ b/app/src/main/res/drawable/ic_new_file.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M12,14V11H10V14H7V16H10V19H12V16H15V14M14,2H6A2,2 0,0 0,4 4V20A2,2 0,0 0,6 22H18A2,2 0,0 0,20 20V8L14,2M18,20H6V4H13V9H18" />
diff --git a/app/src/main/res/drawable/ic_new_folder.xml b/app/src/main/res/drawable/ic_new_folder.xml
index 7443727a5..502c93097 100755
--- a/app/src/main/res/drawable/ic_new_folder.xml
+++ b/app/src/main/res/drawable/ic_new_folder.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M12,12H14V10H16V12H18V14H16V16H14V14H12V12M22,8V18C22,19.11 21.11,20 20,20H4C2.89,20 2,19.11 2,18V6C2,4.89 2.89,4 4,4H10L12,6H20C21.11,6 22,6.89 22,8M20,8H4V18H20V8Z" />
diff --git a/app/src/main/res/drawable/ic_open_project.xml b/app/src/main/res/drawable/ic_open_project.xml
index 468b2935b..45e1879a5 100755
--- a/app/src/main/res/drawable/ic_open_project.xml
+++ b/app/src/main/res/drawable/ic_open_project.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M6.1,10L4,18V8H21A2,2 0,0 0,19 6H12L10,4H4A2,2 0,0 0,2 6V18A2,2 0,0 0,4 20H19C19.9,20 20.7,19.4 20.9,18.5L23.2,10H6.1M19,18H6L7.6,12H20.6L19,18Z" />
diff --git a/app/src/main/res/drawable/ic_package.xml b/app/src/main/res/drawable/ic_package.xml
index 984fefa42..629dd4587 100755
--- a/app/src/main/res/drawable/ic_package.xml
+++ b/app/src/main/res/drawable/ic_package.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L10.11,5.22L16,8.61L17.96,7.5L12,4.15M6.04,7.5L12,10.85L13.96,9.75L8.08,6.35L6.04,7.5M5,15.91L11,19.29V12.58L5,9.21V15.91M19,15.91V9.21L13,12.58V19.29L19,15.91Z" />
diff --git a/app/src/main/res/drawable/ic_password_input.xml b/app/src/main/res/drawable/ic_password_input.xml
index 23e9bdeff..3b2f75eab 100644
--- a/app/src/main/res/drawable/ic_password_input.xml
+++ b/app/src/main/res/drawable/ic_password_input.xml
@@ -1,8 +1,10 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_pick_color.xml b/app/src/main/res/drawable/ic_pick_color.xml
index 70a396c1e..51a2d7051 100644
--- a/app/src/main/res/drawable/ic_pick_color.xml
+++ b/app/src/main/res/drawable/ic_pick_color.xml
@@ -1,8 +1,10 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_preview_layout.xml b/app/src/main/res/drawable/ic_preview_layout.xml
index dc2d065be..e040f3672 100755
--- a/app/src/main/res/drawable/ic_preview_layout.xml
+++ b/app/src/main/res/drawable/ic_preview_layout.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M19,19H5V5H19M19,3H5A2,2 0,0 0,3 5V19A2,2 0,0 0,5 21H19A2,2 0,0 0,21 19V5A2,2 0,0 0,19 3M13.96,12.29L11.21,15.83L9.25,13.47L6.5,17H17.5L13.96,12.29Z" />
diff --git a/app/src/main/res/drawable/ic_rebuild.xml b/app/src/main/res/drawable/ic_rebuild.xml
index c87311fbf..cc9237aad 100755
--- a/app/src/main/res/drawable/ic_rebuild.xml
+++ b/app/src/main/res/drawable/ic_rebuild.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M12,5V1L7,6L12,11V7A6,6 0,0 1,18 13A6,6 0,0 1,12 19A6,6 0,0 1,6 13H4A8,8 0,0 0,12 21A8,8 0,0 0,20 13A8,8 0,0 0,12 5Z" />
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_redo.xml b/app/src/main/res/drawable/ic_redo.xml
index 381f0fc4a..1db16790b 100755
--- a/app/src/main/res/drawable/ic_redo.xml
+++ b/app/src/main/res/drawable/ic_redo.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M18.4,10.6C16.55,9 14.15,8 11.5,8C6.85,8 2.92,11.03 1.54,15.22L3.9,16C4.95,12.81 7.95,10.5 11.5,10.5C13.45,10.5 15.23,11.22 16.62,12.38L13,16H22V7L18.4,10.6Z" />
diff --git a/app/src/main/res/drawable/ic_run.xml b/app/src/main/res/drawable/ic_run.xml
index eb0a107e2..791e626ad 100755
--- a/app/src/main/res/drawable/ic_run.xml
+++ b/app/src/main/res/drawable/ic_run.xml
@@ -2,9 +2,9 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M8,5.14V19.14L19,12.14L8,5.14Z" />
diff --git a/app/src/main/res/drawable/ic_run_debug.xml b/app/src/main/res/drawable/ic_run_debug.xml
index 9e7449128..95459450b 100755
--- a/app/src/main/res/drawable/ic_run_debug.xml
+++ b/app/src/main/res/drawable/ic_run_debug.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M15,9A1,1 0,0 1,14 8A1,1 0,0 1,15 7A1,1 0,0 1,16 8A1,1 0,0 1,15 9M9,9A1,1 0,0 1,8 8A1,1 0,0 1,9 7A1,1 0,0 1,10 8A1,1 0,0 1,9 9M16.12,4.37L18.22,2.27L17.4,1.44L15.09,3.75C14.16,3.28 13.11,3 12,3C10.88,3 9.84,3.28 8.91,3.75L6.6,1.44L5.78,2.27L7.88,4.37C6.14,5.64 5,7.68 5,10V11H19V10C19,7.68 17.86,5.64 16.12,4.37M5,16C5,19.86 8.13,23 12,23A7,7 0,0 0,19 16V12H5V16Z" />
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_run_outline.xml b/app/src/main/res/drawable/ic_run_outline.xml
index feb3e3672..4caed50ca 100755
--- a/app/src/main/res/drawable/ic_run_outline.xml
+++ b/app/src/main/res/drawable/ic_run_outline.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M8.5,8.64L13.77,12L8.5,15.36V8.64M6.5,5V19L17.5,12" />
diff --git a/app/src/main/res/drawable/ic_run_release.xml b/app/src/main/res/drawable/ic_run_release.xml
index 7754d4d6e..ddb8924bf 100755
--- a/app/src/main/res/drawable/ic_run_release.xml
+++ b/app/src/main/res/drawable/ic_run_release.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M3,20.5V3.5C3,2.91 3.34,2.39 3.84,2.15L13.69,12L3.84,21.85C3.34,21.6 3,21.09 3,20.5M16.81,15.12L6.05,21.34L14.54,12.85L16.81,15.12M20.16,10.81C20.5,11.08 20.75,11.5 20.75,12C20.75,12.5 20.53,12.9 20.18,13.18L17.89,14.5L15.39,12L17.89,9.5L20.16,10.81M6.05,2.66L16.81,8.88L14.54,11.15L6.05,2.66Z" />
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_save.xml b/app/src/main/res/drawable/ic_save.xml
index 166dd6e6b..e10924fe8 100755
--- a/app/src/main/res/drawable/ic_save.xml
+++ b/app/src/main/res/drawable/ic_save.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M17,3H5C3.89,3 3,3.9 3,5V19C3,20.1 3.89,21 5,21H19C20.1,21 21,20.1 21,19V7L17,3M19,19H5V5H16.17L19,7.83V19M12,12C10.34,12 9,13.34 9,15S10.34,18 12,18 15,16.66 15,15 13.66,12 12,12M6,6H15V10H6V6Z" />
diff --git a/app/src/main/res/drawable/ic_search.xml b/app/src/main/res/drawable/ic_search.xml
index 090645da3..3c52c84f1 100755
--- a/app/src/main/res/drawable/ic_search.xml
+++ b/app/src/main/res/drawable/ic_search.xml
@@ -2,9 +2,9 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M9.5,3A6.5,6.5 0,0 1,16 9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0,0 1,3 9.5A6.5,6.5 0,0 1,9.5 3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" />
diff --git a/app/src/main/res/drawable/ic_search_file.xml b/app/src/main/res/drawable/ic_search_file.xml
index f1b43f9d0..94a4e863d 100755
--- a/app/src/main/res/drawable/ic_search_file.xml
+++ b/app/src/main/res/drawable/ic_search_file.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M14,2H6A2,2 0,0 0,4 4V20A2,2 0,0 0,6 22H13C12.59,21.75 12.2,21.44 11.86,21.1C11.53,20.77 11.25,20.4 11,20H6V4H13V9H18V10.18C18.71,10.34 19.39,10.61 20,11V8L14,2M20.31,18.9C21.64,16.79 21,14 18.91,12.68C16.8,11.35 14,12 12.69,14.08C11.35,16.19 12,18.97 14.09,20.3C15.55,21.23 17.41,21.23 18.88,20.32L22,23.39L23.39,22L20.31,18.9M16.5,19A2.5,2.5 0,0 1,14 16.5A2.5,2.5 0,0 1,16.5 14A2.5,2.5 0,0 1,19 16.5A2.5,2.5 0,0 1,16.5 19Z" />
diff --git a/app/src/main/res/drawable/ic_search_next.xml b/app/src/main/res/drawable/ic_search_next.xml
index 8fd5a6c6b..6fcd95931 100644
--- a/app/src/main/res/drawable/ic_search_next.xml
+++ b/app/src/main/res/drawable/ic_search_next.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_search_previous.xml b/app/src/main/res/drawable/ic_search_previous.xml
index d81a72f3b..ec79e302b 100644
--- a/app/src/main/res/drawable/ic_search_previous.xml
+++ b/app/src/main/res/drawable/ic_search_previous.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_search_project.xml b/app/src/main/res/drawable/ic_search_project.xml
index fd9218f3b..ed6be9136 100755
--- a/app/src/main/res/drawable/ic_search_project.xml
+++ b/app/src/main/res/drawable/ic_search_project.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M16.5,12C19,12 21,14 21,16.5C21,17.38 20.75,18.21 20.31,18.9L23.39,22L22,23.39L18.88,20.32C18.19,20.75 17.37,21 16.5,21C14,21 12,19 12,16.5C12,14 14,12 16.5,12M16.5,14A2.5,2.5 0,0 0,14 16.5A2.5,2.5 0,0 0,16.5 19A2.5,2.5 0,0 0,19 16.5A2.5,2.5 0,0 0,16.5 14M19,8H3V18H10.17C10.34,18.72 10.63,19.39 11,20H3C1.89,20 1,19.1 1,18V6C1,4.89 1.89,4 3,4H9L11,6H19A2,2 0,0 1,21 8V11.81C20.42,11.26 19.75,10.81 19,10.5V8Z" />
diff --git a/app/src/main/res/drawable/ic_search_replace.xml b/app/src/main/res/drawable/ic_search_replace.xml
index dcd686788..4c5883a49 100644
--- a/app/src/main/res/drawable/ic_search_replace.xml
+++ b/app/src/main/res/drawable/ic_search_replace.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml
index bc5fd887a..a8a60d8c9 100755
--- a/app/src/main/res/drawable/ic_settings.xml
+++ b/app/src/main/res/drawable/ic_settings.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M12,8A4,4 0,0 1,16 12A4,4 0,0 1,12 16A4,4 0,0 1,8 12A4,4 0,0 1,12 8M12,10A2,2 0,0 0,10 12A2,2 0,0 0,12 14A2,2 0,0 0,14 12A2,2 0,0 0,12 10M10,22C9.75,22 9.54,21.82 9.5,21.58L9.13,18.93C8.5,18.68 7.96,18.34 7.44,17.94L4.95,18.95C4.73,19.03 4.46,18.95 4.34,18.73L2.34,15.27C2.21,15.05 2.27,14.78 2.46,14.63L4.57,12.97L4.5,12L4.57,11L2.46,9.37C2.27,9.22 2.21,8.95 2.34,8.73L4.34,5.27C4.46,5.05 4.73,4.96 4.95,5.05L7.44,6.05C7.96,5.66 8.5,5.32 9.13,5.07L9.5,2.42C9.54,2.18 9.75,2 10,2H14C14.25,2 14.46,2.18 14.5,2.42L14.87,5.07C15.5,5.32 16.04,5.66 16.56,6.05L19.05,5.05C19.27,4.96 19.54,5.05 19.66,5.27L21.66,8.73C21.79,8.95 21.73,9.22 21.54,9.37L19.43,11L19.5,12L19.43,13L21.54,14.63C21.73,14.78 21.79,15.05 21.66,15.27L19.66,18.73C19.54,18.95 19.27,19.04 19.05,18.95L16.56,17.95C16.04,18.34 15.5,18.68 14.87,18.93L14.5,21.58C14.46,21.82 14.25,22 14,22H10M11.25,4L10.88,6.61C9.68,6.86 8.62,7.5 7.85,8.39L5.44,7.35L4.69,8.65L6.8,10.2C6.4,11.37 6.4,12.64 6.8,13.8L4.68,15.36L5.43,16.66L7.86,15.62C8.63,16.5 9.68,17.14 10.87,17.38L11.24,20H12.76L13.13,17.39C14.32,17.14 15.37,16.5 16.14,15.62L18.57,16.66L19.32,15.36L17.2,13.81C17.6,12.64 17.6,11.37 17.2,10.2L19.31,8.65L18.56,7.35L16.15,8.39C15.38,7.5 14.32,6.86 13.12,6.62L12.75,4H11.25Z" />
diff --git a/app/src/main/res/drawable/ic_share.xml b/app/src/main/res/drawable/ic_share.xml
index 4f1446be1..4e779736a 100755
--- a/app/src/main/res/drawable/ic_share.xml
+++ b/app/src/main/res/drawable/ic_share.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M18,16.08C17.24,16.08 16.56,16.38 16.04,16.85L8.91,12.7C8.96,12.47 9,12.24 9,12S8.96,11.53 8.91,11.3L15.96,7.19C16.5,7.69 17.21,8 18,8C19.66,8 21,6.66 21,5S19.66,2 18,2 15,3.34 15,5C15,5.24 15.04,5.47 15.09,5.7L8.04,9.81C7.5,9.31 6.79,9 6,9C4.34,9 3,10.34 3,12S4.34,15 6,15C6.79,15 7.5,14.69 8.04,14.19L15.16,18.34C15.11,18.55 15.08,18.77 15.08,19C15.08,20.61 16.39,21.91 18,21.91S20.92,20.61 20.92,19C20.92,17.39 19.61,16.08 18,16.08M18,4C18.55,4 19,4.45 19,5S18.55,6 18,6 17,5.55 17,5 17.45,4 18,4M6,13C5.45,13 5,12.55 5,12S5.45,11 6,11 7,11.45 7,12 6.55,13 6,13M18,20C17.45,20 17,19.55 17,19S17.45,18 18,18 19,18.45 19,19 18.55,20 18,20Z" />
diff --git a/app/src/main/res/drawable/ic_stop_daemons.xml b/app/src/main/res/drawable/ic_stop_daemons.xml
index b8cdb470c..b90cea49b 100755
--- a/app/src/main/res/drawable/ic_stop_daemons.xml
+++ b/app/src/main/res/drawable/ic_stop_daemons.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M12,2A10,10 0,0 0,2 12A10,10 0,0 0,12 22A10,10 0,0 0,22 12A10,10 0,0 0,12 2M12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4M9,9V15H15V9" />
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_sync.xml b/app/src/main/res/drawable/ic_sync.xml
index f16a1b06e..49e364ba0 100755
--- a/app/src/main/res/drawable/ic_sync.xml
+++ b/app/src/main/res/drawable/ic_sync.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_tab.xml b/app/src/main/res/drawable/ic_tab.xml
index b06319833..440a0cac4 100755
--- a/app/src/main/res/drawable/ic_tab.xml
+++ b/app/src/main/res/drawable/ic_tab.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M20,18H22V6H20M11.59,7.41L15.17,11H1V13H15.17L11.59,16.58L13,18L19,12L13,6L11.59,7.41Z" />
diff --git a/app/src/main/res/drawable/ic_target_sdk.xml b/app/src/main/res/drawable/ic_target_sdk.xml
index 3df5e1f3e..091b1a82e 100755
--- a/app/src/main/res/drawable/ic_target_sdk.xml
+++ b/app/src/main/res/drawable/ic_target_sdk.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M11,2V4.07C7.38,4.53 4.53,7.38 4.07,11H2V13H4.07C4.53,16.62 7.38,19.47 11,19.93V22H13V19.93C16.62,19.47 19.47,16.62 19.93,13H22V11H19.93C19.47,7.38 16.62,4.53 13,4.07V2M11,6.08V8H13V6.09C15.5,6.5 17.5,8.5 17.92,11H16V13H17.91C17.5,15.5 15.5,17.5 13,17.92V16H11V17.91C8.5,17.5 6.5,15.5 6.08,13H8V11H6.09C6.5,8.5 8.5,6.5 11,6.08M12,11A1,1 0,0 0,11 12A1,1 0,0 0,12 13A1,1 0,0 0,13 12A1,1 0,0 0,12 11Z" />
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_telegram.xml b/app/src/main/res/drawable/ic_telegram.xml
index 8b5b8e770..ee1e9085a 100755
--- a/app/src/main/res/drawable/ic_telegram.xml
+++ b/app/src/main/res/drawable/ic_telegram.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M9.78,18.65L10.06,14.42L17.74,7.5C18.08,7.19 17.67,7.04 17.22,7.31L7.74,13.3L3.64,12C2.76,11.75 2.75,11.14 3.84,10.7L19.81,4.54C20.54,4.21 21.24,4.72 20.96,5.84L18.24,18.65C18.05,19.56 17.5,19.78 16.74,19.36L12.6,16.3L10.61,18.23C10.38,18.46 10.19,18.65 9.78,18.65Z" />
diff --git a/app/src/main/res/drawable/ic_terminal.xml b/app/src/main/res/drawable/ic_terminal.xml
index 21e97a288..420234453 100755
--- a/app/src/main/res/drawable/ic_terminal.xml
+++ b/app/src/main/res/drawable/ic_terminal.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M21.83,4C22.32,4 22.63,4.4 22.5,4.89L19.34,19.11C19.23,19.6 18.75,20 18.26,20H2.17C1.68,20 1.37,19.6 1.5,19.11L4.66,4.89C4.77,4.4 5.25,4 5.74,4H21.83M15.83,16H11.83C11.37,16 11,16.38 11,16.84C11,17.31 11.37,17.69 11.83,17.69H15.83C16.3,17.69 16.68,17.31 16.68,16.84C16.68,16.38 16.3,16 15.83,16M5.78,16.28C5.38,16.56 5.29,17.11 5.57,17.5C5.85,17.92 6.41,18 6.81,17.73C14.16,12.56 14.21,12.5 14.26,12.47C14.44,12.31 14.53,12.09 14.54,11.87C14.55,11.67 14.5,11.5 14.38,11.31L9.46,6.03C9.13,5.67 8.57,5.65 8.21,6C7.85,6.32 7.83,6.88 8.16,7.24L12.31,11.68L5.78,16.28Z" />
diff --git a/app/src/main/res/drawable/ic_text_lower.xml b/app/src/main/res/drawable/ic_text_lower.xml
index aec47d537..b0878283c 100644
--- a/app/src/main/res/drawable/ic_text_lower.xml
+++ b/app/src/main/res/drawable/ic_text_lower.xml
@@ -1,8 +1,10 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_text_size.xml b/app/src/main/res/drawable/ic_text_size.xml
index a260f895b..5bb47df3d 100755
--- a/app/src/main/res/drawable/ic_text_size.xml
+++ b/app/src/main/res/drawable/ic_text_size.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M2,4V7H7V19H10V7H15V4H2M21,9H12V12H15V19H18V12H21V9Z" />
diff --git a/app/src/main/res/drawable/ic_undo.xml b/app/src/main/res/drawable/ic_undo.xml
index 102999c3d..4d4421d99 100755
--- a/app/src/main/res/drawable/ic_undo.xml
+++ b/app/src/main/res/drawable/ic_undo.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M12.5,8C9.85,8 7.45,9 5.6,10.6L2,7V16H11L7.38,12.38C8.77,11.22 10.54,10.5 12.5,10.5C16.04,10.5 19.05,12.81 20.1,16L22.47,15.22C21.08,11.03 17.15,8 12.5,8Z" />
diff --git a/app/src/main/res/drawable/ic_view_select_parent.xml b/app/src/main/res/drawable/ic_view_select_parent.xml
index 4754c87c9..80cd99cf3 100644
--- a/app/src/main/res/drawable/ic_view_select_parent.xml
+++ b/app/src/main/res/drawable/ic_view_select_parent.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_website.xml b/app/src/main/res/drawable/ic_website.xml
index cd54f775c..5eea09784 100755
--- a/app/src/main/res/drawable/ic_website.xml
+++ b/app/src/main/res/drawable/ic_website.xml
@@ -2,10 +2,10 @@
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ android:pathData="M16.36,14C16.44,13.34 16.5,12.68 16.5,12C16.5,11.32 16.44,10.66 16.36,10H19.74C19.9,10.64 20,11.31 20,12C20,12.69 19.9,13.36 19.74,14M14.59,19.56C15.19,18.45 15.65,17.25 15.97,16H18.92C17.96,17.65 16.43,18.93 14.59,19.56M14.34,14H9.66C9.56,13.34 9.5,12.68 9.5,12C9.5,11.32 9.56,10.65 9.66,10H14.34C14.43,10.65 14.5,11.32 14.5,12C14.5,12.68 14.43,13.34 14.34,14M12,19.96C11.17,18.76 10.5,17.43 10.09,16H13.91C13.5,17.43 12.83,18.76 12,19.96M8,8H5.08C6.03,6.34 7.57,5.06 9.4,4.44C8.8,5.55 8.35,6.75 8,8M5.08,16H8C8.35,17.25 8.8,18.45 9.4,19.56C7.57,18.93 6.03,17.65 5.08,16M4.26,14C4.1,13.36 4,12.69 4,12C4,11.31 4.1,10.64 4.26,10H7.64C7.56,10.66 7.5,11.32 7.5,12C7.5,12.68 7.56,13.34 7.64,14M12,4.03C12.83,5.23 13.5,6.57 13.91,8H10.09C10.5,6.57 11.17,5.23 12,4.03M18.92,8H15.97C15.65,6.75 15.19,5.55 14.59,4.44C16.43,5.07 17.96,6.34 18.92,8M12,2C6.47,2 2,6.5 2,12A10,10 0,0 0,12 22A10,10 0,0 0,22 12A10,10 0,0 0,12 2Z" />
diff --git a/app/src/main/res/drawable/ic_widget_button.xml b/app/src/main/res/drawable/ic_widget_button.xml
index 6f92f63e4..4f4c8cc20 100755
--- a/app/src/main/res/drawable/ic_widget_button.xml
+++ b/app/src/main/res/drawable/ic_widget_button.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_widget_checkbox.xml b/app/src/main/res/drawable/ic_widget_checkbox.xml
index 298bc37e8..738c6892c 100755
--- a/app/src/main/res/drawable/ic_widget_checkbox.xml
+++ b/app/src/main/res/drawable/ic_widget_checkbox.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_widget_checked_textview.xml b/app/src/main/res/drawable/ic_widget_checked_textview.xml
index e24b9835c..92b83f17f 100755
--- a/app/src/main/res/drawable/ic_widget_checked_textview.xml
+++ b/app/src/main/res/drawable/ic_widget_checked_textview.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_widget_edittext.xml b/app/src/main/res/drawable/ic_widget_edittext.xml
index 5034d67b1..3f5e59806 100755
--- a/app/src/main/res/drawable/ic_widget_edittext.xml
+++ b/app/src/main/res/drawable/ic_widget_edittext.xml
@@ -1,8 +1,10 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_widget_image.xml b/app/src/main/res/drawable/ic_widget_image.xml
index d35859dd5..0a221c919 100755
--- a/app/src/main/res/drawable/ic_widget_image.xml
+++ b/app/src/main/res/drawable/ic_widget_image.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_widget_linear.xml b/app/src/main/res/drawable/ic_widget_linear.xml
index 563ecabab..1d9e7b20c 100644
--- a/app/src/main/res/drawable/ic_widget_linear.xml
+++ b/app/src/main/res/drawable/ic_widget_linear.xml
@@ -19,24 +19,24 @@
android:height="24dp"
android:viewportWidth="512"
android:viewportHeight="512">
-
-
-
-
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_widget_progress.xml b/app/src/main/res/drawable/ic_widget_progress.xml
index 3062e2fce..605ea95cf 100755
--- a/app/src/main/res/drawable/ic_widget_progress.xml
+++ b/app/src/main/res/drawable/ic_widget_progress.xml
@@ -1,38 +1,38 @@
-
-
-
-
+ android:width="24.0dp"
+ android:height="24.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_widget_radio_button.xml b/app/src/main/res/drawable/ic_widget_radio_button.xml
index 3937722fa..cd02753b7 100755
--- a/app/src/main/res/drawable/ic_widget_radio_button.xml
+++ b/app/src/main/res/drawable/ic_widget_radio_button.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_widget_seekbar.xml b/app/src/main/res/drawable/ic_widget_seekbar.xml
index 1b0c1cdc7..ebc94f101 100755
--- a/app/src/main/res/drawable/ic_widget_seekbar.xml
+++ b/app/src/main/res/drawable/ic_widget_seekbar.xml
@@ -1,8 +1,10 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_widget_spinner.xml b/app/src/main/res/drawable/ic_widget_spinner.xml
index 3dbfedba2..f5b891d07 100755
--- a/app/src/main/res/drawable/ic_widget_spinner.xml
+++ b/app/src/main/res/drawable/ic_widget_spinner.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_widget_textview.xml b/app/src/main/res/drawable/ic_widget_textview.xml
index fb98d9932..ee5982a93 100755
--- a/app/src/main/res/drawable/ic_widget_textview.xml
+++ b/app/src/main/res/drawable/ic_widget_textview.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_wrap_text.xml b/app/src/main/res/drawable/ic_wrap_text.xml
index 1dbb4c0fd..b7988d532 100644
--- a/app/src/main/res/drawable/ic_wrap_text.xml
+++ b/app/src/main/res/drawable/ic_wrap_text.xml
@@ -1,10 +1,10 @@
-
+ android:viewportHeight="24">
+
diff --git a/app/src/main/res/drawable/ic_xml_attribute.xml b/app/src/main/res/drawable/ic_xml_attribute.xml
index ab8fd2549..f4b1aba06 100644
--- a/app/src/main/res/drawable/ic_xml_attribute.xml
+++ b/app/src/main/res/drawable/ic_xml_attribute.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml
index 3db8d2d3d..39015db90 100755
--- a/app/src/main/res/layout/activity_about.xml
+++ b/app/src/main/res/layout/activity_about.xml
@@ -1,86 +1,86 @@
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ app:layoutDescription="@xml/motion_about">
-
-
-
+
+
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/icon_anchor">
-
+
-
+
-
-
-
-
-
+
+
+
+
-
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/subtitle">
+
-
+ android:id="@+id/items"
+ layout="@layout/layout_about_items"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="24dp" />
+
diff --git a/app/src/main/res/layout/activity_crash_handler.xml b/app/src/main/res/layout/activity_crash_handler.xml
index 7f49b1383..33c3a5c79 100644
--- a/app/src/main/res/layout/activity_crash_handler.xml
+++ b/app/src/main/res/layout/activity_crash_handler.xml
@@ -1,5 +1,4 @@
-
-
-
+ tools:context=".DesignerActivity">
+ android:background="@drawable/bg_design_container_background"
+ android:orientation="vertical" />
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 89c8edf8c..7b1e1619f 100755
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -6,19 +6,19 @@
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical"
- tools:ignore="RtlCompat" >
+ tools:ignore="RtlCompat">
+ android:gravity="center"
+ app:layout_behavior="com.google.android.material.appbar.AppBarLayout$Behavior">
+ android:layout_height="wrap_content">
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml
index ad9957364..f459d6c21 100755
--- a/app/src/main/res/layout/activity_splash.xml
+++ b/app/src/main/res/layout/activity_splash.xml
@@ -3,32 +3,32 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
-
+
-
+
-
+
diff --git a/app/src/main/res/layout/activity_terminal.xml b/app/src/main/res/layout/activity_terminal.xml
index e5836b387..c1eaa6685 100755
--- a/app/src/main/res/layout/activity_terminal.xml
+++ b/app/src/main/res/layout/activity_terminal.xml
@@ -2,15 +2,15 @@
-
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
-
+ android:background="@android:color/black"
+ tools:ignore="MissingClass" />
+
diff --git a/app/src/main/res/layout/fragment_non_editable_editor.xml b/app/src/main/res/layout/fragment_non_editable_editor.xml
index d4881a809..ab606d7ff 100644
--- a/app/src/main/res/layout/fragment_non_editable_editor.xml
+++ b/app/src/main/res/layout/fragment_non_editable_editor.xml
@@ -15,8 +15,7 @@
~ along with AndroidIDE. If not, see .
-->
-
\ No newline at end of file
+ android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_about_items.xml b/app/src/main/res/layout/layout_about_items.xml
index 789355e8c..916596569 100755
--- a/app/src/main/res/layout/layout_about_items.xml
+++ b/app/src/main/res/layout/layout_about_items.xml
@@ -1,157 +1,156 @@
-
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:paddingTop="16dp">
-
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/app/src/main/res/layout/layout_attr_editor_sheet_item.xml b/app/src/main/res/layout/layout_attr_editor_sheet_item.xml
index e97e19d4c..ca2d133c4 100644
--- a/app/src/main/res/layout/layout_attr_editor_sheet_item.xml
+++ b/app/src/main/res/layout/layout_attr_editor_sheet_item.xml
@@ -15,32 +15,31 @@
~ along with AndroidIDE. If not, see .
-->
-
+ android:focusable="true"
+ android:gravity="center_vertical"
+ android:orientation="horizontal"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp">
+ android:src="@drawable/ic_xml_attribute" />
+ android:textColor="@color/primaryTextColorLight"
+ android:textSize="16sp"
+ tools:text="layout_height" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_banner.xml b/app/src/main/res/layout/layout_banner.xml
index ac022d767..9d532f316 100755
--- a/app/src/main/res/layout/layout_banner.xml
+++ b/app/src/main/res/layout/layout_banner.xml
@@ -6,58 +6,58 @@
android:layout_height="wrap_content"
android:orientation="vertical">
-
+
+ android:id="@+id/contentTextView"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_marginTop="24dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginBottom="8dp"
+ android:alpha="0.8"
+ android:letterSpacing="0.02"
+ android:lineSpacingExtra="7sp"
+ android:textColor="@color/primaryTextColor"
+ android:textSize="14sp"
+ android:textStyle="normal"
+ app:layout_constraintBottom_toTopOf="@+id/rightButton"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toEndOf="@id/contentIconView"
+ app:layout_constraintTop_toTopOf="parent" />
+ android:id="@+id/leftButton"
+ style="@style/Widget.MaterialComponents.Button.TextButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="8dp"
+ android:textColor="@color/primaryTextColor"
+ android:textSize="14sp"
+ app:layout_constraintBottom_toBottomOf="@+id/rightButton"
+ app:layout_constraintEnd_toStartOf="@+id/rightButton"
+ app:layout_constraintTop_toTopOf="@+id/rightButton"
+ app:rippleColor="@color/primaryDarkColor" />
+ android:id="@+id/rightButton"
+ style="@style/Widget.MaterialComponents.Button.TextButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginEnd="16dp"
+ android:layout_marginBottom="9dp"
+ android:textColor="@color/primaryTextColor"
+ android:textSize="14sp"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:rippleColor="@color/primaryDarkColor" />
diff --git a/app/src/main/res/layout/layout_code_editor.xml b/app/src/main/res/layout/layout_code_editor.xml
index 02cb4faec..a333fcab8 100644
--- a/app/src/main/res/layout/layout_code_editor.xml
+++ b/app/src/main/res/layout/layout_code_editor.xml
@@ -1,36 +1,35 @@
-
-
+
+
-
+ android:layout_height="0dp"
+ android:layout_weight="1.0" />
+
+ android:padding="8dp"
+ android:singleLine="true"
+ android:textColor="@color/primaryTextColor"
+ android:textSize="12sp" />
-
+
diff --git a/app/src/main/res/layout/layout_completion_item.xml b/app/src/main/res/layout/layout_completion_item.xml
index 9407c5256..7633aea20 100755
--- a/app/src/main/res/layout/layout_completion_item.xml
+++ b/app/src/main/res/layout/layout_completion_item.xml
@@ -1,88 +1,88 @@
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/relativeLayout2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@color/primaryLightColor"
+ android:gravity="center_vertical"
+ tools:ignore="SmallSp">
-
+
-
+
-
+
-
+
-
+
diff --git a/app/src/main/res/layout/layout_crash_report.xml b/app/src/main/res/layout/layout_crash_report.xml
index dcab09f31..479b4251b 100644
--- a/app/src/main/res/layout/layout_crash_report.xml
+++ b/app/src/main/res/layout/layout_crash_report.xml
@@ -49,8 +49,8 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp"
android:layout_marginTop="4dp"
+ android:layout_marginEnd="16dp"
android:text="@string/msg_report_crash"
android:textColor="@color/secondaryTextColor_light"
android:textSize="14sp"
@@ -79,7 +79,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textColor="@color/secondaryColor"
- tools:text="This is an error message."/>
+ tools:text="This is an error message." />
diff --git a/app/src/main/res/layout/layout_create_file_java.xml b/app/src/main/res/layout/layout_create_file_java.xml
index 19b0e0b85..c6a2bc9be 100755
--- a/app/src/main/res/layout/layout_create_file_java.xml
+++ b/app/src/main/res/layout/layout_create_file_java.xml
@@ -1,88 +1,87 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/app/src/main/res/layout/layout_diagnostic_group.xml b/app/src/main/res/layout/layout_diagnostic_group.xml
index e499b2c8e..438b74b19 100755
--- a/app/src/main/res/layout/layout_diagnostic_group.xml
+++ b/app/src/main/res/layout/layout_diagnostic_group.xml
@@ -1,23 +1,22 @@
-
-
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="@color/content_background"
+ android:orientation="vertical"
+ tools:ignore="Overdraw">
+
-
+ layout="@layout/layout_diagnostic_item" />
+
+ android:paddingEnd="16dp" />
diff --git a/app/src/main/res/layout/layout_diagnostic_info.xml b/app/src/main/res/layout/layout_diagnostic_info.xml
index 744d49f31..5802b8baa 100755
--- a/app/src/main/res/layout/layout_diagnostic_info.xml
+++ b/app/src/main/res/layout/layout_diagnostic_info.xml
@@ -1,9 +1,9 @@
+ android:textIsSelectable="true"
+ android:textSize="11sp" />
diff --git a/app/src/main/res/layout/layout_diagnostic_item.xml b/app/src/main/res/layout/layout_diagnostic_item.xml
index c56c560a2..074288293 100755
--- a/app/src/main/res/layout/layout_diagnostic_item.xml
+++ b/app/src/main/res/layout/layout_diagnostic_item.xml
@@ -1,35 +1,34 @@
-
+ android:clickable="true"
+ android:descendantFocusability="blocksDescendants"
+ android:focusable="true"
+ android:foreground="?attr/selectableItemBackground"
+ android:gravity="top|start"
+ android:orientation="horizontal"
+ android:paddingStart="16dp"
+ android:paddingTop="8dp"
+ android:paddingEnd="16dp"
+ android:paddingBottom="8dp"
+ tools:ignore="UnusedAttribute">
-
+
-
+
diff --git a/app/src/main/res/layout/layout_dialog_text_input.xml b/app/src/main/res/layout/layout_dialog_text_input.xml
index 4094eafbd..9bd755d00 100755
--- a/app/src/main/res/layout/layout_dialog_text_input.xml
+++ b/app/src/main/res/layout/layout_dialog_text_input.xml
@@ -1,29 +1,28 @@
-
+
-
+
-
+
-
+
diff --git a/app/src/main/res/layout/layout_editor_file_tree.xml b/app/src/main/res/layout/layout_editor_file_tree.xml
index 0d938169e..8b321a23b 100755
--- a/app/src/main/res/layout/layout_editor_file_tree.xml
+++ b/app/src/main/res/layout/layout_editor_file_tree.xml
@@ -1,26 +1,25 @@
-
-
-
+
-
+
+
+
diff --git a/app/src/main/res/layout/layout_filetree_item.xml b/app/src/main/res/layout/layout_filetree_item.xml
index 699ef086f..b48828e3c 100755
--- a/app/src/main/res/layout/layout_filetree_item.xml
+++ b/app/src/main/res/layout/layout_filetree_item.xml
@@ -1,31 +1,30 @@
-
+
-
+
-
+
-
+
diff --git a/app/src/main/res/layout/layout_loading_wizard.xml b/app/src/main/res/layout/layout_loading_wizard.xml
index b4044cfaf..e78747820 100644
--- a/app/src/main/res/layout/layout_loading_wizard.xml
+++ b/app/src/main/res/layout/layout_loading_wizard.xml
@@ -9,9 +9,9 @@
+ android:layout_height="wrap_content"
+ android:indeterminate="true" />
+ android:text="@string/wizard_loading"
+ android:textSize="24sp" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_nav_header.xml b/app/src/main/res/layout/layout_nav_header.xml
index 0a8f81545..d9db6286c 100755
--- a/app/src/main/res/layout/layout_nav_header.xml
+++ b/app/src/main/res/layout/layout_nav_header.xml
@@ -1,32 +1,31 @@
-
+
-
+
-
+
diff --git a/app/src/main/res/layout/layout_optionssheet_item.xml b/app/src/main/res/layout/layout_optionssheet_item.xml
index d4bee6311..3697ca99c 100755
--- a/app/src/main/res/layout/layout_optionssheet_item.xml
+++ b/app/src/main/res/layout/layout_optionssheet_item.xml
@@ -1,33 +1,33 @@
+ android:orientation="vertical"
+ android:paddingTop="16dp"
+ android:paddingBottom="16dp">
-
+
-
+
diff --git a/app/src/main/res/layout/layout_progress_sheet.xml b/app/src/main/res/layout/layout_progress_sheet.xml
index 62826ea11..eb9ea5b19 100755
--- a/app/src/main/res/layout/layout_progress_sheet.xml
+++ b/app/src/main/res/layout/layout_progress_sheet.xml
@@ -1,51 +1,50 @@
-
+
-
+
-
+
-
+
-
+
diff --git a/app/src/main/res/layout/layout_search_project.xml b/app/src/main/res/layout/layout_search_project.xml
index bee069eda..885f1addc 100755
--- a/app/src/main/res/layout/layout_search_project.xml
+++ b/app/src/main/res/layout/layout_search_project.xml
@@ -1,64 +1,63 @@
-
-
+
+ android:paddingTop="12dp"
+ android:paddingEnd="16dp"
+ android:paddingBottom="12dp">
+ android:layout_marginBottom="8dp"
+ android:text="@string/msg_search_modules" />
+ android:layout_marginBottom="16dp"
+ android:orientation="vertical" />
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
-
+
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
-
+
-
+
diff --git a/app/src/main/res/layout/layout_search_result_group.xml b/app/src/main/res/layout/layout_search_result_group.xml
index b734ab7db..07876b3ad 100755
--- a/app/src/main/res/layout/layout_search_result_group.xml
+++ b/app/src/main/res/layout/layout_search_result_group.xml
@@ -1,64 +1,63 @@
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ android:clipToPadding="false"
+ android:fillViewport="true"
+ android:paddingStart="16dp"
+ tools:ignore="RtlSymmetry">
-
+
-
+
diff --git a/app/src/main/res/layout/layout_search_result_item.xml b/app/src/main/res/layout/layout_search_result_item.xml
index 52cc2bc0c..400175671 100755
--- a/app/src/main/res/layout/layout_search_result_item.xml
+++ b/app/src/main/res/layout/layout_search_result_item.xml
@@ -1,26 +1,25 @@
-
+
-
+
diff --git a/app/src/main/res/layout/layout_sheet.xml b/app/src/main/res/layout/layout_sheet.xml
index 4ce02192f..82146be26 100755
--- a/app/src/main/res/layout/layout_sheet.xml
+++ b/app/src/main/res/layout/layout_sheet.xml
@@ -1,46 +1,45 @@
-
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+ app:rippleColor="@color/rippleHighlightColor" />
+ android:orientation="horizontal" />
+ android:paddingBottom="8dp" />
diff --git a/app/src/main/res/layout/layout_simple_icon_text.xml b/app/src/main/res/layout/layout_simple_icon_text.xml
index c84268b64..a649e7016 100755
--- a/app/src/main/res/layout/layout_simple_icon_text.xml
+++ b/app/src/main/res/layout/layout_simple_icon_text.xml
@@ -14,8 +14,7 @@
~ You should have received a copy of the GNU General Public License
~ along with AndroidIDE. If not, see .
-->
-
+ android:padding="4dp"
+ android:scaleType="fitCenter"
+ android:src="@drawable/ic_android" />
+ android:gravity="center"
+ android:singleLine="true"
+ android:textColor="@color/symbolInput_text" />
diff --git a/app/src/main/res/layout/layout_text_size_slider.xml b/app/src/main/res/layout/layout_text_size_slider.xml
index 0835a1f1b..0a7031fe6 100755
--- a/app/src/main/res/layout/layout_text_size_slider.xml
+++ b/app/src/main/res/layout/layout_text_size_slider.xml
@@ -1,27 +1,26 @@
-
-
-
+
+
+
diff --git a/app/src/main/res/layout/setup_footer.xml b/app/src/main/res/layout/setup_footer.xml
index 8f56056f6..dfbaa42c9 100644
--- a/app/src/main/res/layout/setup_footer.xml
+++ b/app/src/main/res/layout/setup_footer.xml
@@ -1,33 +1,31 @@
+ android:paddingBottom="8dp">
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp"
+ android:text="@string/exit"
+ android:textColor="?attr/colorOnSurface" />
+ android:layout_weight="1" />
+ android:text="@string/next"
+ android:textColor="@color/primaryTextColor" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/wizard_details.xml b/app/src/main/res/layout/wizard_details.xml
index 64f498dcb..daf25738a 100644
--- a/app/src/main/res/layout/wizard_details.xml
+++ b/app/src/main/res/layout/wizard_details.xml
@@ -1,27 +1,26 @@
+ android:paddingTop="8dp"
+ android:paddingEnd="16dp">
+ app:startIconTint="@color/primaryIconColor">
+ app:startIconTint="@color/primaryIconColor">
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/til_package_name"
+ app:placeholderText="/storage/emulated/0/AppProjects/MyApplication">
+ app:layout_constraintTop_toBottomOf="@+id/til_save_location">
+ app:layout_constraintTop_toBottomOf="@+id/til_language">
+ app:startIconTint="@color/primaryIconColor">
+ app:startIconTint="@color/primaryIconColor">
+ android:paddingEnd="16dp">
@@ -24,10 +24,10 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
- android:maxLines="2"
android:gravity="center_horizontal"
+ android:maxLines="2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/template_icon"
- tools:text="Empty Activity"/>
+ tools:text="Empty Activity" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/wizard_templates.xml b/app/src/main/res/layout/wizard_templates.xml
index dc9393104..dc4a24100 100644
--- a/app/src/main/res/layout/wizard_templates.xml
+++ b/app/src/main/res/layout/wizard_templates.xml
@@ -1,8 +1,8 @@
+ android:layout_height="match_parent">
-
+
+ android:id="@+id/editornav_group_project"
+ android:title="@string/group_project">
+ android:title="@string/btn_terminal" />
+ android:title="@string/title_close_project" />
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml
index 02ba289c2..3cb339cf4 100644
--- a/app/src/main/res/values-pt-rBR/strings.xml
+++ b/app/src/main/res/values-pt-rBR/strings.xml
@@ -1,301 +1,301 @@
- AndroidIDE
- O AndroidIDE usa uma versão modificada do JDK que é licenciada sob a GNU General Public License v2.0. O código fonte e a licença do JDK estão disponíveis em:
- Licenças de código aberto
- O AndroidIDE usa bibliotecas de código aberto. Você pode encontrar a fonte e a licença das bibliotecas usadas clicando nos links abaixo.
- Licenciado em:
- E-mail
- Site
- AndroidIDE v\u2022 %s
- AndroidIDE %1$s para %2$s
- Simplesmente, uma IDE para Android
- Falha ao extrair o nome do pacote!
- AndroidIDE é um ambiente de desenvolvimento integrado para criar aplicativos Android em seu smartphone Android. Ele suporta:\n1. Grade \n2. OpenJDK 11.0.1.\n3. Completador avançado de código Java\n4. Preenchimento Automático de XML \n5. Suporta Kotlin e muito mais.\n\nFaça o download do AndroidIDE em https://androidide.com
- Se estiver enfrentando problemas ao usar o AndroidIDE ou ao criar aplicativos para Android, você pode participar do Grupo do Telegram e pedir ajuda por lá.\n\nVocê também pode enviar sugestões em nosso e-mail.
- Discutir e ajudar
- GitHub
- Precisa de ajuda?
- Outro
- Compartilhar com amigos
- Preferências da IDE
- Discussões no Telegram
- Não tenho nada para te mostrar…
- Terminal
- Redefinir
- Registros do aplicativo
- Registros da IDE
- Imagem inicial
- Começar
+ AndroidIDE
+ O AndroidIDE usa uma versão modificada do JDK que é licenciada sob a GNU General Public License v2.0. O código fonte e a licença do JDK estão disponíveis em:
+ Licenças de código aberto
+ O AndroidIDE usa bibliotecas de código aberto. Você pode encontrar a fonte e a licença das bibliotecas usadas clicando nos links abaixo.
+ Licenciado em:
+ E-mail
+ Site
+ AndroidIDE v\u2022 %s
+ AndroidIDE %1$s para %2$s
+ Simplesmente, uma IDE para Android
+ Falha ao extrair o nome do pacote!
+ AndroidIDE é um ambiente de desenvolvimento integrado para criar aplicativos Android em seu smartphone Android. Ele suporta:\n1. Grade \n2. OpenJDK 11.0.1.\n3. Completador avançado de código Java\n4. Preenchimento Automático de XML \n5. Suporta Kotlin e muito mais.\n\nFaça o download do AndroidIDE em https://androidide.com
+ Se estiver enfrentando problemas ao usar o AndroidIDE ou ao criar aplicativos para Android, você pode participar do Grupo do Telegram e pedir ajuda por lá.\n\nVocê também pode enviar sugestões em nosso e-mail.
+ Discutir e ajudar
+ GitHub
+ Precisa de ajuda?
+ Outro
+ Compartilhar com amigos
+ Preferências da IDE
+ Discussões no Telegram
+ Não tenho nada para te mostrar…
+ Terminal
+ Redefinir
+ Registros do aplicativo
+ Registros da IDE
+ Imagem inicial
+ Começar
- Não foi possível executar a correção rápida
- Executando ação de código…
- Desde a API %d
- Removido na API %d
- Descontinuado na API %d
- Encontrando referências…
- Encontrando definição…
- Definição não encontrada
- Nenhuma referência encontrada
- Diagnósticos
+ Não foi possível executar a correção rápida
+ Executando ação de código…
+ Desde a API %d
+ Removido na API %d
+ Descontinuado na API %d
+ Encontrando referências…
+ Encontrando definição…
+ Definição não encontrada
+ Nenhuma referência encontrada
+ Diagnósticos
- Falha na instalação
- Prepare-se para algo incrível!
- O arquivo selecionado não é um diretório!
- Por favor, escolha apenas um diretório
- Aguarde um momento…
- Dispositivo não suportado
- Infelizmente, seu dispositivo não é compatível no momento. Lamentamos o inconveniente.\n\nABIs de CPU compatíveis: aarch64 e armeabi-v7a
+ Falha na instalação
+ Prepare-se para algo incrível!
+ O arquivo selecionado não é um diretório!
+ Por favor, escolha apenas um diretório
+ Aguarde um momento…
+ Dispositivo não suportado
+ Infelizmente, seu dispositivo não é compatível no momento. Lamentamos o inconveniente.\n\nABIs de CPU compatíveis: aarch64 e armeabi-v7a
- Lint
- lintDebug
- lintRelease
- Construir
- assembleDebug
- Saída de compilação
- assembleRelease
- Construções Lint
- Limpar e construir
- Limpar
- Criar AAB
- Tipos de construções
- Execução rápida
- Os arquivos Gradle foram alterados. Por favor, reconstrua seu projeto para sincronizar dependências e configurações.
- Preparando
- Preparando. A primeira compilação pode levar de 10 a 15 minutos!
- Gradle Wrapper não está disponível!\nInstalando um padrão. Gradle v7.4 será baixado se necessário.
- Recebendo o status de Daemon, aguarde…
- Status do daemon Gradle
- Instalar APK(s)
- Limpar registros
- Executar
- Gradle
- Primeira compilação
- Esta é a primeira vez que compila depois de instalar o AndroidIDE. A primeira compilação geralmente leva tempo, pois o Gradle baixa todas as dependências e plugins. Esse processo pode levar cerca de 10 a 15 minutos. Mas isto depende totalmente de sua velocidade de internet.\n\nSeja paciente…
+ Lint
+ lintDebug
+ lintRelease
+ Construir
+ assembleDebug
+ Saída de compilação
+ assembleRelease
+ Construções Lint
+ Limpar e construir
+ Limpar
+ Criar AAB
+ Tipos de construções
+ Execução rápida
+ Os arquivos Gradle foram alterados. Por favor, reconstrua seu projeto para sincronizar dependências e configurações.
+ Preparando
+ Preparando. A primeira compilação pode levar de 10 a 15 minutos!
+ Gradle Wrapper não está disponível!\nInstalando um padrão. Gradle v7.4 será baixado se necessário.
+ Recebendo o status de Daemon, aguarde…
+ Status do daemon Gradle
+ Instalar APK(s)
+ Limpar registros
+ Executar
+ Gradle
+ Primeira compilação
+ Esta é a primeira vez que compila depois de instalar o AndroidIDE. A primeira compilação geralmente leva tempo, pois o Gradle baixa todas as dependências e plugins. Esse processo pode levar cerca de 10 a 15 minutos. Mas isto depende totalmente de sua velocidade de internet.\n\nSeja paciente…
-
- Criar projeto
- SDK mínimo
- SDK de destino
- Novo projeto
- Nome do pacote
- Nome do aplicativo
- Comece seu novo projeto incrível!
- Abrir último projeto?
- Você quer que eu abra o último projeto aberto? O projeto aberto foi:\n%s
- Projeto
- Fechar este projeto
- O último projeto aberto não existe!
- Criar novo projeto
- Abrir projeto existente
- Fechar projeto
- Tem certeza de que deseja fechar este projeto? Todos os daemons do Gradle iniciados serão interrompidos após o fechamento deste projeto.
- Já existe um projeto com o mesmo nome!
+
+ Criar projeto
+ SDK mínimo
+ SDK de destino
+ Novo projeto
+ Nome do pacote
+ Nome do aplicativo
+ Comece seu novo projeto incrível!
+ Abrir último projeto?
+ Você quer que eu abra o último projeto aberto? O projeto aberto foi:\n%s
+ Projeto
+ Fechar este projeto
+ O último projeto aberto não existe!
+ Criar novo projeto
+ Abrir projeto existente
+ Fechar projeto
+ Tem certeza de que deseja fechar este projeto? Todos os daemons do Gradle iniciados serão interrompidos após o fechamento deste projeto.
+ Já existe um projeto com o mesmo nome!
-
- Projeto Básico
- Um projeto básico com AppCompat Toolbar e um botão de ação flutuante
- Um projeto vazio com barra de ferramentas padrão. Adequado quando você quer fazer todas as coisas básicas sozinho.
- Projeto com barra de ferramentas AppCompat, DrawerLayout e NavigationView
- Projeto vazio
- Projeto navigation drawer
- Jogo LibGDX
- Projeto de jogo LibGDX configurado para renderizar uma imagem como exemplo.
+
+ Projeto Básico
+ Um projeto básico com AppCompat Toolbar e um botão de ação flutuante
+ Um projeto vazio com barra de ferramentas padrão. Adequado quando você quer fazer todas as coisas básicas sozinho.
+ Projeto com barra de ferramentas AppCompat, DrawerLayout e NavigationView
+ Projeto vazio
+ Projeto navigation drawer
+ Jogo LibGDX
+ Projeto de jogo LibGDX configurado para renderizar uma imagem como exemplo.
- Salvar
- Pesquisar
- Pesquisar no arquivo
- Pesquisar no projeto
- Pesquisar em módulos
- Nenhum módulo encontrado no projeto
- Filtrar extensões de arquivo (opcional)
- Separado por \'|\'
- Por favor, digite o texto
- Selecione os módulos para Pesquisar
- Encontrando no projeto, aguarde…
- Resultados de pesquisa
- Copiando arquivos
- Gravando arquivos
- Copiando recursos
- Falha ao criar o diretório do projeto!
- Falha ao gravar o arquivo: %s
- Falha ao copiar o modelo para o armazenamento!
- Falha ao criar diretório de projeto temporário!
- Projeto criado com sucesso!
- Iniciando o processo de gravação
- Falha ao criar pasta!
- Falha ao criar arquivo!
- Pasta criada com sucesso!
- Arquivo criado com sucesso!
- A pasta já existe!
- O arquivo já existe!
- Nome inválido!
- Criar
- Se o nome tiver um separador de arquivos "/", são criados diretórios se ele contiver algo depois dele.
- Nome da pasta
- Nome do arquivo
- Novo nome
- Novo arquivo
- Nova classe Java
- Novo recurso XML
- Nova pasta
- Confirmar exclusão
- Tem certeza de que deseja excluir:\n%s?
- Copiado com sucesso!
- Digite um novo nome para o arquivo/pasta.
- Renomeado com sucesso!
- Não foi possível renomear o arquivo!
- Excluído com sucesso!
- Não foi possível excluir o arquivo!
- Copiar caminho
- Renomear
- Excluir
- Opções para arquivos
- Fechar tudo
- Fechar outros
- Fechar
- Todos os foram arquivos salvos!
- Destino: %s/
- Drawable
- Layout
- Menu
- Outro
- Class
- Activity
- Interface
- Enum
- Verificando permissões de armazenamento
- Falha ao listar arquivos de projeto!
- Não é possível prosseguir sem permissões de armazenamento
- Permissões de armazenamento concedidas!
+ Salvar
+ Pesquisar
+ Pesquisar no arquivo
+ Pesquisar no projeto
+ Pesquisar em módulos
+ Nenhum módulo encontrado no projeto
+ Filtrar extensões de arquivo (opcional)
+ Separado por \'|\'
+ Por favor, digite o texto
+ Selecione os módulos para Pesquisar
+ Encontrando no projeto, aguarde…
+ Resultados de pesquisa
+ Copiando arquivos
+ Gravando arquivos
+ Copiando recursos
+ Falha ao criar o diretório do projeto!
+ Falha ao gravar o arquivo: %s
+ Falha ao copiar o modelo para o armazenamento!
+ Falha ao criar diretório de projeto temporário!
+ Projeto criado com sucesso!
+ Iniciando o processo de gravação
+ Falha ao criar pasta!
+ Falha ao criar arquivo!
+ Pasta criada com sucesso!
+ Arquivo criado com sucesso!
+ A pasta já existe!
+ O arquivo já existe!
+ Nome inválido!
+ Criar
+ Se o nome tiver um separador de arquivos "/", são criados diretórios se ele contiver algo depois dele.
+ Nome da pasta
+ Nome do arquivo
+ Novo nome
+ Novo arquivo
+ Nova classe Java
+ Novo recurso XML
+ Nova pasta
+ Confirmar exclusão
+ Tem certeza de que deseja excluir:\n%s?
+ Copiado com sucesso!
+ Digite um novo nome para o arquivo/pasta.
+ Renomeado com sucesso!
+ Não foi possível renomear o arquivo!
+ Excluído com sucesso!
+ Não foi possível excluir o arquivo!
+ Copiar caminho
+ Renomear
+ Excluir
+ Opções para arquivos
+ Fechar tudo
+ Fechar outros
+ Fechar
+ Todos os foram arquivos salvos!
+ Destino: %s/
+ Drawable
+ Layout
+ Menu
+ Outro
+ Class
+ Activity
+ Interface
+ Enum
+ Verificando permissões de armazenamento
+ Falha ao listar arquivos de projeto!
+ Não é possível prosseguir sem permissões de armazenamento
+ Permissões de armazenamento concedidas!
- Desfazer
- Refazer
- - Copiar
- - Texto para Pesquisar
+ Desfazer
+ Refazer
+ - Copiar
+ - Texto para Pesquisar
- Tamanho da fonte do editor
- Sobre o AndroidIDE
- Limpar caches do Gradle
- Limpe o diretório de caches do Gradle. Isso excluirá todas as dependências baixadas pelo Gradle. Os arquivos necessários serão baixados novamente na próxima compilação.
- Comandos adicionais do Gradle
- Escolha comandos adicionais que serão adicionados durante a execução de cada tarefa
- Tamanho da fonte
- Tamanho da fonte do editor
- Non-printable painting flags
- Escolha quais caracteres non-printable devem ser desenhados pelo editor.
- Desenhar sequências de cores hexadecimais
- O editor deve desenhar uma string de cor hexadecimal?
- Editor
- Construção e execução
- Abrir último projeto
- Se ativado, a IDE lembrará seu último projeto aberto e o abrirá toda vez que você reiniciar.
- Confirmar abertura do projeto
- Pergunte antes de abrir o último projeto
- Usar shell do sistema no terminal
- Se ativado, \'/system/bin/sh\' será usado no terminal.
- Geral
- Tamanho das tab
- Especifique o número de espaços para as tabs
- Preferências
- Registro de alterações
- Por favor, escolha o tamanho da fonte padrão do editor:
- Isso excluirá o diretório de caches criado pelo Gradle. Se você excluí-lo, a próxima compilação pode demorar um pouco mais do que o normal, pois o Gradle fará o download dos arquivos necessários novamente.\nIMPORTANTE: Isso também excluirá o AAPT2. Você precisará reinstalá-lo, caso contrário, ocorrerá uma falha de compilação.\n\nTem certeza de que deseja excluir os caches?
- Quebra de linha
- Usar quebras de linha no editor
- Ativar lupa
- Zoom de texto na posição do cursor ao selecionar texto no editor
+ Tamanho da fonte do editor
+ Sobre o AndroidIDE
+ Limpar caches do Gradle
+ Limpe o diretório de caches do Gradle. Isso excluirá todas as dependências baixadas pelo Gradle. Os arquivos necessários serão baixados novamente na próxima compilação.
+ Comandos adicionais do Gradle
+ Escolha comandos adicionais que serão adicionados durante a execução de cada tarefa
+ Tamanho da fonte
+ Tamanho da fonte do editor
+ Non-printable painting flags
+ Escolha quais caracteres non-printable devem ser desenhados pelo editor.
+ Desenhar sequências de cores hexadecimais
+ O editor deve desenhar uma string de cor hexadecimal?
+ Editor
+ Construção e execução
+ Abrir último projeto
+ Se ativado, a IDE lembrará seu último projeto aberto e o abrirá toda vez que você reiniciar.
+ Confirmar abertura do projeto
+ Pergunte antes de abrir o último projeto
+ Usar shell do sistema no terminal
+ Se ativado, \'/system/bin/sh\' será usado no terminal.
+ Geral
+ Tamanho das tab
+ Especifique o número de espaços para as tabs
+ Preferências
+ Registro de alterações
+ Por favor, escolha o tamanho da fonte padrão do editor:
+ Isso excluirá o diretório de caches criado pelo Gradle. Se você excluí-lo, a próxima compilação pode demorar um pouco mais do que o normal, pois o Gradle fará o download dos arquivos necessários novamente.\nIMPORTANTE: Isso também excluirá o AAPT2. Você precisará reinstalá-lo, caso contrário, ocorrerá uma falha de compilação.\n\nTem certeza de que deseja excluir os caches?
+ Quebra de linha
+ Usar quebras de linha no editor
+ Ativar lupa
+ Zoom de texto na posição do cursor ao selecionar texto no editor
- Não foi possível inicializar as informações do SDK
- Não foi possível visualizar o layout
- Não foi possível inflar o layout
+ Não foi possível inicializar as informações do SDK
+ Não foi possível visualizar o layout
+ Não foi possível inflar o layout
- Não foi possível visualizar o layout!
- Pré-visualização do layout
- Conteúdo principal do designer de interface do usuário
- TextView
- Button
- Android
- CheckBox
- CheckedTextView
- EditText
- ImageButton
- ImageView
- ProgressBar
- RadioButton
- SeekBar
- Spinner
- Layouts
- LinearLayout
- RelativeLayout
- Atributos aplicáveis
- Ações
- Excluir
- Selecionar parent
- Esta visualização não tem um parent
- Por favor, confirme
- Tem certeza?
- Não foi possível excluir a visualização.
- Nenhuma visualização foi adicionada. Clique para adicionar.
- Nenhum formato de atributo está disponível para este atributo.
- Falha ao gerar código XML
- Gerando código XML
- Falha na geração de código
- Falha ao gerar o código XML. Deseja sair mesmo assim?
- UI Designer retornou resultado inválido
- Deslize para cima para ver saída de compilação, logs e muito mais.
- AndroidIDE travou
- Abra um problema no github com o seguinte rastreamento de pilha:
- Clique no botão abaixo para copiar o registro e abrir a página de problemas.
- Copiar e denunciar
- Lendo o arquivo bootstrap…
- Falha na instalação do Bootstrap com a seguinte exceção.
- Traduções
- Instalando o módulo do compilador
- O módulo do compilador está sendo instalado, aguarde…
- Falha na instalação do módulo do compilador. O erro foi:\n%s
- Módulo do compilador instalado com sucesso!
- Expandir seleção
- Combinar as conclusões em letras minúsculas
- Comum
- Java
- Arquivos não salvos
- Alguns arquivos não foram salvos. Gostaria de salvá-los antes de fechar? Os arquivos não salvos são: \n%s
- Salvar antes de fechar os arquivos
- Salve os arquivos antes de fechá-los. Este é um recurso EXPERIMENTAL. Ele espera que você mesmo salve os arquivos.
- Se ativado, a digitação em letras minúsculas sugerirá classes e variáveis.
- Ligaduras de fonte
- Ativar/desativar ligaduras de fonte
+ Não foi possível visualizar o layout!
+ Pré-visualização do layout
+ Conteúdo principal do designer de interface do usuário
+ TextView
+ Button
+ Android
+ CheckBox
+ CheckedTextView
+ EditText
+ ImageButton
+ ImageView
+ ProgressBar
+ RadioButton
+ SeekBar
+ Spinner
+ Layouts
+ LinearLayout
+ RelativeLayout
+ Atributos aplicáveis
+ Ações
+ Excluir
+ Selecionar parent
+ Esta visualização não tem um parent
+ Por favor, confirme
+ Tem certeza?
+ Não foi possível excluir a visualização.
+ Nenhuma visualização foi adicionada. Clique para adicionar.
+ Nenhum formato de atributo está disponível para este atributo.
+ Falha ao gerar código XML
+ Gerando código XML
+ Falha na geração de código
+ Falha ao gerar o código XML. Deseja sair mesmo assim?
+ UI Designer retornou resultado inválido
+ Deslize para cima para ver saída de compilação, logs e muito mais.
+ AndroidIDE travou
+ Abra um problema no github com o seguinte rastreamento de pilha:
+ Clique no botão abaixo para copiar o registro e abrir a página de problemas.
+ Copiar e denunciar
+ Lendo o arquivo bootstrap…
+ Falha na instalação do Bootstrap com a seguinte exceção.
+ Traduções
+ Instalando o módulo do compilador
+ O módulo do compilador está sendo instalado, aguarde…
+ Falha na instalação do módulo do compilador. O erro foi:\n%s
+ Módulo do compilador instalado com sucesso!
+ Expandir seleção
+ Combinar as conclusões em letras minúsculas
+ Comum
+ Java
+ Arquivos não salvos
+ Alguns arquivos não foram salvos. Gostaria de salvá-los antes de fechar? Os arquivos não salvos são: \n%s
+ Salvar antes de fechar os arquivos
+ Salve os arquivos antes de fechá-los. Este é um recurso EXPERIMENTAL. Ele espera que você mesmo salve os arquivos.
+ Se ativado, a digitação em letras minúsculas sugerirá classes e variáveis.
+ Ligaduras de fonte
+ Ativar/desativar ligaduras de fonte
- Sim
- Não
- Não foi possível iniciar a intenção de instalação do APK
- Adicionar atributo
- Pesquisar atributos…
- Valor da dimensão
- Resource dimension
- Resource boolean
- Árvore de arquivos
- Resource color
- Seletor de cores
- Texto da string
- Resource string
- Qualquer referência de resource
- Ações
- Formatar código
- Use a formatação de código no estilo Java do Google
- Use a configuração de formatação de código Java Style do Google para formatar o código fonte Java.
- Dica de senha
- Quando ativado, nenhuma dica de senha será mostrada pelo teclado.
- Anterior
- Substituindo…
+ Sim
+ Não
+ Não foi possível iniciar a intenção de instalação do APK
+ Adicionar atributo
+ Pesquisar atributos…
+ Valor da dimensão
+ Resource dimension
+ Resource boolean
+ Árvore de arquivos
+ Resource color
+ Seletor de cores
+ Texto da string
+ Resource string
+ Qualquer referência de resource
+ Ações
+ Formatar código
+ Use a formatação de código no estilo Java do Google
+ Use a configuração de formatação de código Java Style do Google para formatar o código fonte Java.
+ Dica de senha
+ Quando ativado, nenhuma dica de senha será mostrada pelo teclado.
+ Anterior
+ Substituindo…
\ No newline at end of file
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index 1bbd7226d..467d77750 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -1,5 +1,4 @@
-
-");
+ private static final Pattern MOE_END_STRIP_COMMENT_PATTERN =
+ compile("^");
+ private static final Pattern HTML_COMMENT_PATTERN = fullCommentPattern();
+ private static final Pattern PRE_OPEN_PATTERN = openTagPattern("pre");
+ private static final Pattern PRE_CLOSE_PATTERN = closeTagPattern("pre");
+ private static final Pattern CODE_OPEN_PATTERN = openTagPattern("code");
+ private static final Pattern CODE_CLOSE_PATTERN = closeTagPattern("code");
+ private static final Pattern TABLE_OPEN_PATTERN = openTagPattern("table");
+ private static final Pattern TABLE_CLOSE_PATTERN = closeTagPattern("table");
+ private static final Pattern LIST_OPEN_PATTERN = openTagPattern("ul|ol|dl");
+ private static final Pattern LIST_CLOSE_PATTERN = closeTagPattern("ul|ol|dl");
+ private static final Pattern LIST_ITEM_OPEN_PATTERN = openTagPattern("li|dt|dd");
+ private static final Pattern LIST_ITEM_CLOSE_PATTERN = closeTagPattern("li|dt|dd");
+ private static final Pattern HEADER_OPEN_PATTERN = openTagPattern("h[1-6]");
+ private static final Pattern HEADER_CLOSE_PATTERN = closeTagPattern("h[1-6]");
+ private static final Pattern PARAGRAPH_OPEN_PATTERN = openTagPattern("p");
+ private static final Pattern PARAGRAPH_CLOSE_PATTERN = closeTagPattern("p");
+ private static final Pattern BLOCKQUOTE_OPEN_PATTERN = openTagPattern("blockquote");
+ private static final Pattern BLOCKQUOTE_CLOSE_PATTERN = closeTagPattern("blockquote");
+ private static final Pattern BR_PATTERN = openTagPattern("br");
+ private static final Pattern INLINE_TAG_OPEN_PATTERN = compile("^[{]@\\w*");
+ /*
+ * We exclude < so that we don't swallow following HTML tags. This lets us fix up "foo" (~400
+ * hits in Google-internal code). We will join unnecessarily split "words" (like "foobar ")
+ * in a later step. There's a similar story for braces. I'm not sure I actually need to exclude @
+ * or *. TODO(cpovirk): Try removing them.
+ *
+ * Thanks to the "rejoin" step in joinAdjacentLiteralsAndAdjacentWhitespace(), we could get away
+ * with matching only one character here. That would eliminate the need for the regex entirely.
+ * That might be faster or slower than what we do now.
+ */
+ private static final Pattern LITERAL_PATTERN = compile("^.[^ \t\n@<{}*]*", DOTALL);
+ private final CharStream input;
+ private final NestingCounter braceDepth = new NestingCounter();
+ private final NestingCounter preDepth = new NestingCounter();
+ private final NestingCounter codeDepth = new NestingCounter();
+ private final NestingCounter tableDepth = new NestingCounter();
+ private boolean somethingSinceNewline;
+ private JavadocLexer(CharStream input) {
+ this.input = checkNotNull(input);
+ }
+
+ private static Pattern fullCommentPattern() {
+ return compile("^", DOTALL);
+ }
+
+ private static Pattern openTagPattern(String namePattern) {
+ return compile(format("^<(?:%s)\\b[^>]*>", namePattern), CASE_INSENSITIVE);
+ }
+
+ private static Pattern closeTagPattern(String namePattern) {
+ return compile(format("^(?:%s)\\b[^>]*>", namePattern), CASE_INSENSITIVE);
+ }
+
/** Takes a Javadoc comment, including ∕✱✱ and ✱∕, and returns tokens, including ∕✱✱ and ✱∕. */
static ImmutableList lex(String input) throws LexException {
/*
@@ -81,8 +152,6 @@ final class JavadocLexer {
return NON_UNIX_LINE_ENDING.matcher(input).replaceAll("\n");
}
- private static final Pattern NON_UNIX_LINE_ENDING = Pattern.compile("\r\n?");
-
private static String stripJavadocBeginAndEnd(String input) {
/*
* We do this ahead of time so that the main part of the lexer need not say things like
@@ -93,17 +162,6 @@ final class JavadocLexer {
return input.substring("/**".length(), input.length() - "*/".length());
}
- private final CharStream input;
- private final NestingCounter braceDepth = new NestingCounter();
- private final NestingCounter preDepth = new NestingCounter();
- private final NestingCounter codeDepth = new NestingCounter();
- private final NestingCounter tableDepth = new NestingCounter();
- private boolean somethingSinceNewline;
-
- private JavadocLexer(CharStream input) {
- this.input = checkNotNull(input);
- }
-
private ImmutableList generateTokens() throws LexException {
ImmutableList.Builder tokens = ImmutableList.builder();
@@ -367,6 +425,10 @@ final class JavadocLexer {
*/
}
+ private static boolean hasMultipleNewlines(String s) {
+ return NEWLINE.countIn(s) > 1;
+ }
+
/**
* Replaces whitespace after a {@code href=...>} token with an "optional link break." This allows
* us to output either {@code foo } or {@code \nfoo }, depending on
@@ -491,72 +553,5 @@ final class JavadocLexer {
}
}
- private static final CharMatcher NEWLINE = CharMatcher.is('\n');
-
- private static boolean hasMultipleNewlines(String s) {
- return NEWLINE.countIn(s) > 1;
- }
-
- /*
- * This also eats any trailing whitespace. We would be smart enough to ignore that, anyway --
- * except in the case of / , inside which we otherwise leave whitespace intact.
- *
- * We'd remove the trailing whitespace later on (in JavaCommentsHelper.rewrite), but I feel safer
- * stripping it now: It otherwise might confuse our line-length count, which we use for wrapping.
- */
- private static final Pattern NEWLINE_PATTERN = compile("^[ \t]*\n[ \t]*[*]?[ \t]?");
-
- // We ensure elsewhere that we match this only at the beginning of a line.
- // Only match tags that start with a lowercase letter, to avoid false matches on unescaped
- // annotations inside code blocks.
- // Match "@param " specially in case the is a or other HTML tag we treat specially.
- private static final Pattern FOOTER_TAG_PATTERN = compile("^@(param\\s+<\\w+>|[a-z]\\w*)");
- private static final Pattern MOE_BEGIN_STRIP_COMMENT_PATTERN =
- compile("^");
- private static final Pattern MOE_END_STRIP_COMMENT_PATTERN =
- compile("^");
- private static final Pattern HTML_COMMENT_PATTERN = fullCommentPattern();
- private static final Pattern PRE_OPEN_PATTERN = openTagPattern("pre");
- private static final Pattern PRE_CLOSE_PATTERN = closeTagPattern("pre");
- private static final Pattern CODE_OPEN_PATTERN = openTagPattern("code");
- private static final Pattern CODE_CLOSE_PATTERN = closeTagPattern("code");
- private static final Pattern TABLE_OPEN_PATTERN = openTagPattern("table");
- private static final Pattern TABLE_CLOSE_PATTERN = closeTagPattern("table");
- private static final Pattern LIST_OPEN_PATTERN = openTagPattern("ul|ol|dl");
- private static final Pattern LIST_CLOSE_PATTERN = closeTagPattern("ul|ol|dl");
- private static final Pattern LIST_ITEM_OPEN_PATTERN = openTagPattern("li|dt|dd");
- private static final Pattern LIST_ITEM_CLOSE_PATTERN = closeTagPattern("li|dt|dd");
- private static final Pattern HEADER_OPEN_PATTERN = openTagPattern("h[1-6]");
- private static final Pattern HEADER_CLOSE_PATTERN = closeTagPattern("h[1-6]");
- private static final Pattern PARAGRAPH_OPEN_PATTERN = openTagPattern("p");
- private static final Pattern PARAGRAPH_CLOSE_PATTERN = closeTagPattern("p");
- private static final Pattern BLOCKQUOTE_OPEN_PATTERN = openTagPattern("blockquote");
- private static final Pattern BLOCKQUOTE_CLOSE_PATTERN = closeTagPattern("blockquote");
- private static final Pattern BR_PATTERN = openTagPattern("br");
- private static final Pattern INLINE_TAG_OPEN_PATTERN = compile("^[{]@\\w*");
- /*
- * We exclude < so that we don't swallow following HTML tags. This lets us fix up "foo
" (~400
- * hits in Google-internal code). We will join unnecessarily split "words" (like "foobar ")
- * in a later step. There's a similar story for braces. I'm not sure I actually need to exclude @
- * or *. TODO(cpovirk): Try removing them.
- *
- * Thanks to the "rejoin" step in joinAdjacentLiteralsAndAdjacentWhitespace(), we could get away
- * with matching only one character here. That would eliminate the need for the regex entirely.
- * That might be faster or slower than what we do now.
- */
- private static final Pattern LITERAL_PATTERN = compile("^.[^ \t\n@<{}*]*", DOTALL);
-
- private static Pattern fullCommentPattern() {
- return compile("^", DOTALL);
- }
-
- private static Pattern openTagPattern(String namePattern) {
- return compile(format("^<(?:%s)\\b[^>]*>", namePattern), CASE_INSENSITIVE);
- }
-
- private static Pattern closeTagPattern(String namePattern) {
- return compile(format("^(?:%s)\\b[^>]*>", namePattern), CASE_INSENSITIVE);
- }
-
static class LexException extends Exception {}
}
diff --git a/build-tools/google-java-format/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocWriter.java b/build-tools/google-java-format/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocWriter.java
index 9656d6ecd..4c800f982 100644
--- a/build-tools/google-java-format/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocWriter.java
+++ b/build-tools/google-java-format/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocWriter.java
@@ -74,6 +74,95 @@ final class JavadocWriter {
this.blockIndent = blockIndent;
}
+ @Override
+ public String toString() {
+ return output.toString();
+ }
+
+ private void requestBlankLine() {
+ requestWhitespace(BLANK_LINE);
+ }
+
+ private void requestNewline() {
+ requestWhitespace(NEWLINE);
+ }
+
+ private void writeToken(Token token) {
+ if (requestedMoeBeginStripComment != null) {
+ requestNewline();
+ }
+
+ if (requestedWhitespace == BLANK_LINE
+ && (postWriteModifiedContinuingListCount.isPositive() || continuingFooterTag)) {
+ /*
+ * We don't write blank lines inside lists or footer tags, even in cases where we otherwise
+ * would (e.g., before a
tag). Justification: We don't write blank lines _between_ list
+ * items or footer tags, so it would be strange to write blank lines _within_ one. Of course,
+ * an alternative approach would be to go ahead and write blank lines between items/tags,
+ * either always or only in the case that an item contains a blank line.
+ */
+ requestedWhitespace = NEWLINE;
+ }
+
+ if (requestedWhitespace == BLANK_LINE) {
+ writeBlankLine();
+ requestedWhitespace = NONE;
+ } else if (requestedWhitespace == NEWLINE) {
+ writeNewline();
+ requestedWhitespace = NONE;
+ }
+ boolean needWhitespace = (requestedWhitespace == WHITESPACE);
+
+ /*
+ * Write a newline if necessary to respect the line limit. (But if we're at the beginning of the
+ * line, a newline won't help. Or it might help but only by separating "
veryverylongword,"
+ * which goes against our style.)
+ */
+ if (!atStartOfLine && token.length() + (needWhitespace ? 1 : 0) > remainingOnLine) {
+ writeNewline();
+ }
+ if (!atStartOfLine && needWhitespace) {
+ output.append(" ");
+ remainingOnLine--;
+ }
+
+ if (requestedMoeBeginStripComment != null) {
+ output.append(requestedMoeBeginStripComment.getValue());
+ requestedMoeBeginStripComment = null;
+ indentForMoeEndStripComment = innerIndent();
+ requestNewline();
+ writeToken(token);
+ return;
+ }
+
+ output.append(token.getValue());
+
+ if (!START_OF_LINE_TOKENS.contains(token.getType())) {
+ atStartOfLine = false;
+ }
+
+ /*
+ * TODO(cpovirk): We really want the number of "characters," not chars. Figure out what the
+ * right way of measuring that is (grapheme count (with BreakIterator?)? sum of widths of all
+ * graphemes? I don't think that our style guide is specific about this.). Moreover, I am
+ * probably brushing other problems with surrogates, etc. under the table. Hopefully I mostly
+ * get away with it by joining all non-space, non-tab characters together.
+ *
+ * Possibly the "width" question has no right answer:
+ * http://denisbider.blogspot.com/2015/09/when-monospace-fonts-arent-unicode.html
+ */
+ remainingOnLine -= token.length();
+ requestedWhitespace = NONE;
+ wroteAnythingSignificant = true;
+ }
+
+ private void writeBlankLine() {
+ output.append("\n");
+ appendSpaces(blockIndent + 1);
+ output.append("*");
+ writeNewline();
+ }
+
/**
* Requests whitespace between the previously written token and the next written token. The
* request may be honored, or it may be overridden by a request for "more significant" whitespace,
@@ -83,6 +172,10 @@ final class JavadocWriter {
requestWhitespace(WHITESPACE);
}
+ private void requestWhitespace(RequestedWhitespace requestedWhitespace) {
+ this.requestedWhitespace = max(requestedWhitespace, this.requestedWhitespace);
+ }
+
void requestMoeBeginStripComment(Token token) {
// We queue this up so that we can put it after any requested whitespace.
requestedMoeBeginStripComment = checkNotNull(token);
@@ -97,6 +190,37 @@ final class JavadocWriter {
writeNewline();
}
+ private void writeNewline() {
+ writeNewline(AUTO_INDENT);
+ }
+
+ private void writeNewline(AutoIndent autoIndent) {
+ output.append("\n");
+ appendSpaces(blockIndent + 1);
+ output.append("*");
+ appendSpaces(1);
+ remainingOnLine = JavadocFormatter.MAX_LINE_LENGTH - blockIndent - 3;
+ if (autoIndent == AUTO_INDENT) {
+ appendSpaces(innerIndent());
+ remainingOnLine -= innerIndent();
+ }
+ atStartOfLine = true;
+ }
+
+ private int innerIndent() {
+ int innerIndent = continuingListItemCount.value() * 4 + continuingListCount.value() * 2;
+ if (continuingFooterTag) {
+ innerIndent += 4;
+ }
+ return innerIndent;
+ }
+
+ // If this is a hotspot, keep a String of many spaces around, and call append(string, start,
+ // end).
+ private void appendSpaces(int count) {
+ output.append(Strings.repeat(" ", count));
+ }
+
void writeEndJavadoc() {
output.append("\n");
appendSpaces(blockIndent + 1);
@@ -268,130 +392,6 @@ final class JavadocWriter {
writeToken(token);
}
- @Override
- public String toString() {
- return output.toString();
- }
-
- private void requestBlankLine() {
- requestWhitespace(BLANK_LINE);
- }
-
- private void requestNewline() {
- requestWhitespace(NEWLINE);
- }
-
- private void requestWhitespace(RequestedWhitespace requestedWhitespace) {
- this.requestedWhitespace = max(requestedWhitespace, this.requestedWhitespace);
- }
-
- private void writeToken(Token token) {
- if (requestedMoeBeginStripComment != null) {
- requestNewline();
- }
-
- if (requestedWhitespace == BLANK_LINE
- && (postWriteModifiedContinuingListCount.isPositive() || continuingFooterTag)) {
- /*
- * We don't write blank lines inside lists or footer tags, even in cases where we otherwise
- * would (e.g., before a
tag). Justification: We don't write blank lines _between_ list
- * items or footer tags, so it would be strange to write blank lines _within_ one. Of course,
- * an alternative approach would be to go ahead and write blank lines between items/tags,
- * either always or only in the case that an item contains a blank line.
- */
- requestedWhitespace = NEWLINE;
- }
-
- if (requestedWhitespace == BLANK_LINE) {
- writeBlankLine();
- requestedWhitespace = NONE;
- } else if (requestedWhitespace == NEWLINE) {
- writeNewline();
- requestedWhitespace = NONE;
- }
- boolean needWhitespace = (requestedWhitespace == WHITESPACE);
-
- /*
- * Write a newline if necessary to respect the line limit. (But if we're at the beginning of the
- * line, a newline won't help. Or it might help but only by separating "
veryverylongword,"
- * which goes against our style.)
- */
- if (!atStartOfLine && token.length() + (needWhitespace ? 1 : 0) > remainingOnLine) {
- writeNewline();
- }
- if (!atStartOfLine && needWhitespace) {
- output.append(" ");
- remainingOnLine--;
- }
-
- if (requestedMoeBeginStripComment != null) {
- output.append(requestedMoeBeginStripComment.getValue());
- requestedMoeBeginStripComment = null;
- indentForMoeEndStripComment = innerIndent();
- requestNewline();
- writeToken(token);
- return;
- }
-
- output.append(token.getValue());
-
- if (!START_OF_LINE_TOKENS.contains(token.getType())) {
- atStartOfLine = false;
- }
-
- /*
- * TODO(cpovirk): We really want the number of "characters," not chars. Figure out what the
- * right way of measuring that is (grapheme count (with BreakIterator?)? sum of widths of all
- * graphemes? I don't think that our style guide is specific about this.). Moreover, I am
- * probably brushing other problems with surrogates, etc. under the table. Hopefully I mostly
- * get away with it by joining all non-space, non-tab characters together.
- *
- * Possibly the "width" question has no right answer:
- * http://denisbider.blogspot.com/2015/09/when-monospace-fonts-arent-unicode.html
- */
- remainingOnLine -= token.length();
- requestedWhitespace = NONE;
- wroteAnythingSignificant = true;
- }
-
- private void writeBlankLine() {
- output.append("\n");
- appendSpaces(blockIndent + 1);
- output.append("*");
- writeNewline();
- }
-
- private void writeNewline() {
- writeNewline(AUTO_INDENT);
- }
-
- private void writeNewline(AutoIndent autoIndent) {
- output.append("\n");
- appendSpaces(blockIndent + 1);
- output.append("*");
- appendSpaces(1);
- remainingOnLine = JavadocFormatter.MAX_LINE_LENGTH - blockIndent - 3;
- if (autoIndent == AUTO_INDENT) {
- appendSpaces(innerIndent());
- remainingOnLine -= innerIndent();
- }
- atStartOfLine = true;
- }
-
- private int innerIndent() {
- int innerIndent = continuingListItemCount.value() * 4 + continuingListCount.value() * 2;
- if (continuingFooterTag) {
- innerIndent += 4;
- }
- return innerIndent;
- }
-
- // If this is a hotspot, keep a String of many spaces around, and call append(string, start,
- // end).
- private void appendSpaces(int count) {
- output.append(Strings.repeat(" ", count));
- }
-
/**
* The kind of whitespace that has been requested between the previous and next tokens. The order
* of the values is significant: It goes from lowest priority to highest. For example, if the
diff --git a/build-tools/google-java-format/src/main/java/com/google/googlejavaformat/java/javadoc/Token.java b/build-tools/google-java-format/src/main/java/com/google/googlejavaformat/java/javadoc/Token.java
index d617824b0..89bfd8900 100644
--- a/build-tools/google-java-format/src/main/java/com/google/googlejavaformat/java/javadoc/Token.java
+++ b/build-tools/google-java-format/src/main/java/com/google/googlejavaformat/java/javadoc/Token.java
@@ -20,6 +20,30 @@ package com.google.googlejavaformat.java.javadoc;
* are in {@link JavadocLexer}.
*/
final class Token {
+ private final Type type;
+ private final String value;
+ Token(Type type, String value) {
+ this.type = type;
+ this.value = value;
+ }
+
+ @Override
+ public String toString() {
+ return "\n" + getType() + ": " + getValue();
+ }
+
+ Type getType() {
+ return type;
+ }
+
+ String getValue() {
+ return value;
+ }
+
+ int length() {
+ return value.length();
+ }
+
/**
* Javadoc token type.
*
@@ -103,29 +127,4 @@ final class Token {
LITERAL,
;
}
-
- private final Type type;
- private final String value;
-
- Token(Type type, String value) {
- this.type = type;
- this.value = value;
- }
-
- Type getType() {
- return type;
- }
-
- String getValue() {
- return value;
- }
-
- int length() {
- return value.length();
- }
-
- @Override
- public String toString() {
- return "\n" + getType() + ": " + getValue();
- }
}
diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/CancelChecker.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/CancelChecker.java
index cd921da9a..670a6d93f 100644
--- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/CancelChecker.java
+++ b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/CancelChecker.java
@@ -16,9 +16,6 @@ import java.util.concurrent.CancellationException;
/** Used for processing requests with cancellation support. */
public interface CancelChecker {
- /** Throw a {@link CancellationException} if the currently processed request has been canceled. */
- void checkCanceled();
-
/** Check for cancellation without throwing an exception. */
default boolean isCanceled() {
try {
@@ -28,4 +25,7 @@ public interface CancelChecker {
}
return false;
}
+
+ /** Throw a {@link CancellationException} if the currently processed request has been canceled. */
+ void checkCanceled();
}
diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/CompletableFutures.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/CompletableFutures.java
index 3c5295724..3a0e842ab 100644
--- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/CompletableFutures.java
+++ b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/CompletableFutures.java
@@ -56,14 +56,14 @@ public final class CompletableFutures {
this.future = future;
}
- @Override
- public void checkCanceled() {
- if (future.isCancelled()) throw new CancellationException();
- }
-
@Override
public boolean isCanceled() {
return future.isCancelled();
}
+
+ @Override
+ public void checkCanceled() {
+ if (future.isCancelled()) throw new CancellationException();
+ }
}
}
diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/JsonRpcException.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/JsonRpcException.java
index 65937577e..91c3f430a 100644
--- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/JsonRpcException.java
+++ b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/JsonRpcException.java
@@ -19,6 +19,12 @@ import java.nio.channels.ClosedChannelException;
/** An exception thrown when accessing the JSON-RPC communication channel fails. */
public class JsonRpcException extends RuntimeException {
+ private static final long serialVersionUID = -7952794305289314670L;
+
+ public JsonRpcException(Throwable cause) {
+ super(cause);
+ }
+
/** Whether the given exception indicates that the currently accessed stream has been closed. */
public static boolean indicatesStreamClosed(Throwable thr) {
return thr instanceof InterruptedIOException
@@ -30,10 +36,4 @@ public class JsonRpcException extends RuntimeException {
|| "Broken pipe (Write failed)".equals(thr.getMessage()))
|| thr instanceof JsonRpcException && indicatesStreamClosed(thr.getCause());
}
-
- private static final long serialVersionUID = -7952794305289314670L;
-
- public JsonRpcException(Throwable cause) {
- super(cause);
- }
}
diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/Launcher.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/Launcher.java
index eaea321fa..4966ab7db 100644
--- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/Launcher.java
+++ b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/Launcher.java
@@ -11,6 +11,18 @@
******************************************************************************/
package org.eclipse.lsp4j.jsonrpc;
+import com.google.gson.GsonBuilder;
+
+import org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor;
+import org.eclipse.lsp4j.jsonrpc.json.JsonRpcMethod;
+import org.eclipse.lsp4j.jsonrpc.json.JsonRpcMethodProvider;
+import org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler;
+import org.eclipse.lsp4j.jsonrpc.json.StreamMessageConsumer;
+import org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer;
+import org.eclipse.lsp4j.jsonrpc.messages.ResponseError;
+import org.eclipse.lsp4j.jsonrpc.services.ServiceEndpoints;
+import org.eclipse.lsp4j.jsonrpc.validation.ReflectiveMessageValidator;
+
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
@@ -24,18 +36,6 @@ import java.util.concurrent.Future;
import java.util.function.Consumer;
import java.util.function.Function;
-import org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor;
-import org.eclipse.lsp4j.jsonrpc.json.JsonRpcMethod;
-import org.eclipse.lsp4j.jsonrpc.json.JsonRpcMethodProvider;
-import org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler;
-import org.eclipse.lsp4j.jsonrpc.json.StreamMessageConsumer;
-import org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer;
-import org.eclipse.lsp4j.jsonrpc.messages.ResponseError;
-import org.eclipse.lsp4j.jsonrpc.services.ServiceEndpoints;
-import org.eclipse.lsp4j.jsonrpc.validation.ReflectiveMessageValidator;
-
-import com.google.gson.GsonBuilder;
-
/**
* This is the entry point for applications that use LSP4J. A Launcher does all the wiring that is
* necessary to connect your endpoint via an input stream and an output stream.
@@ -260,6 +260,25 @@ public interface Launcher {
// ------------------------------ Builder Class ------------------------------//
+ /**
+ * Start a thread that listens to the input stream. The thread terminates when the stream is
+ * closed.
+ *
+ * @return a future that returns {@code null} when the listener thread is terminated
+ */
+ Future startListening();
+
+ // ---------------------------- Interface Methods ----------------------------//
+
+ /** Returns the proxy instance that implements the remote service interfaces. */
+ T getRemoteProxy();
+
+ /**
+ * Returns the remote endpoint. Use this one to send generic {@code request} or {@code notify}
+ * methods to the remote services.
+ */
+ RemoteEndpoint getRemoteEndpoint();
+
/**
* The launcher builder wires up all components for JSON-RPC communication.
*
@@ -377,6 +396,27 @@ public interface Launcher {
else return new MessageJsonHandler(supportedMethods);
}
+ /** Gather all JSON-RPC methods from the local and remote services. */
+ protected Map getSupportedMethods() {
+ Map supportedMethods = new LinkedHashMap<>();
+ // Gather the supported methods of remote interfaces
+ for (Class> interface_ : remoteInterfaces) {
+ supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(interface_));
+ }
+
+ // Gather the supported methods of local services
+ for (Object localService : localServices) {
+ if (localService instanceof JsonRpcMethodProvider) {
+ JsonRpcMethodProvider rpcMethodProvider = (JsonRpcMethodProvider) localService;
+ supportedMethods.putAll(rpcMethodProvider.supportedMethods());
+ } else {
+ supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(localService.getClass()));
+ }
+ }
+
+ return supportedMethods;
+ }
+
/** Create the remote endpoint that communicates with the local services. */
protected RemoteEndpoint createRemoteEndpoint(MessageJsonHandler jsonHandler) {
MessageConsumer outgoingMessageStream = new StreamMessageConsumer(output, jsonHandler);
@@ -391,6 +431,20 @@ public interface Launcher {
return remoteEndpoint;
}
+ protected MessageConsumer wrapMessageConsumer(MessageConsumer consumer) {
+ MessageConsumer result = consumer;
+ if (messageTracer != null) {
+ result = messageTracer.apply(consumer);
+ }
+ if (validateMessages) {
+ result = new ReflectiveMessageValidator(result);
+ }
+ if (messageWrapper != null) {
+ result = messageWrapper.apply(result);
+ }
+ return result;
+ }
+
/** Create the proxy for calling methods on the remote service. */
@SuppressWarnings("unchecked")
protected T createProxy(RemoteEndpoint remoteEndpoint) {
@@ -416,59 +470,5 @@ public interface Launcher {
ConcurrentMessageProcessor msgProcessor) {
return new StandardLauncher(execService, remoteProxy, remoteEndpoint, msgProcessor);
}
-
- protected MessageConsumer wrapMessageConsumer(MessageConsumer consumer) {
- MessageConsumer result = consumer;
- if (messageTracer != null) {
- result = messageTracer.apply(consumer);
- }
- if (validateMessages) {
- result = new ReflectiveMessageValidator(result);
- }
- if (messageWrapper != null) {
- result = messageWrapper.apply(result);
- }
- return result;
- }
-
- /** Gather all JSON-RPC methods from the local and remote services. */
- protected Map getSupportedMethods() {
- Map supportedMethods = new LinkedHashMap<>();
- // Gather the supported methods of remote interfaces
- for (Class> interface_ : remoteInterfaces) {
- supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(interface_));
- }
-
- // Gather the supported methods of local services
- for (Object localService : localServices) {
- if (localService instanceof JsonRpcMethodProvider) {
- JsonRpcMethodProvider rpcMethodProvider = (JsonRpcMethodProvider) localService;
- supportedMethods.putAll(rpcMethodProvider.supportedMethods());
- } else {
- supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(localService.getClass()));
- }
- }
-
- return supportedMethods;
- }
}
-
- // ---------------------------- Interface Methods ----------------------------//
-
- /**
- * Start a thread that listens to the input stream. The thread terminates when the stream is
- * closed.
- *
- * @return a future that returns {@code null} when the listener thread is terminated
- */
- Future startListening();
-
- /** Returns the proxy instance that implements the remote service interfaces. */
- T getRemoteProxy();
-
- /**
- * Returns the remote endpoint. Use this one to send generic {@code request} or {@code notify}
- * methods to the remote services.
- */
- RemoteEndpoint getRemoteEndpoint();
}
diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageIssueException.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageIssueException.java
index c3d33d238..a0a95b539 100644
--- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageIssueException.java
+++ b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageIssueException.java
@@ -11,6 +11,9 @@
******************************************************************************/
package org.eclipse.lsp4j.jsonrpc;
+import org.eclipse.lsp4j.jsonrpc.messages.Message;
+import org.eclipse.lsp4j.jsonrpc.messages.MessageIssue;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -18,9 +21,6 @@ import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import org.eclipse.lsp4j.jsonrpc.messages.Message;
-import org.eclipse.lsp4j.jsonrpc.messages.MessageIssue;
-
/**
* An exception thrown to notify the caller of a {@link MessageConsumer} that one or more issues
* were found while parsing or validating a message. This information can be passed to a {@link
diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageIssueHandler.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageIssueHandler.java
index 283be649e..24466921d 100644
--- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageIssueHandler.java
+++ b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/MessageIssueHandler.java
@@ -11,11 +11,11 @@
******************************************************************************/
package org.eclipse.lsp4j.jsonrpc;
-import java.util.List;
-
import org.eclipse.lsp4j.jsonrpc.messages.Message;
import org.eclipse.lsp4j.jsonrpc.messages.MessageIssue;
+import java.util.List;
+
public interface MessageIssueHandler {
/**
diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/RemoteEndpoint.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/RemoteEndpoint.java
index 60ee6f902..146599e89 100644
--- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/RemoteEndpoint.java
+++ b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/RemoteEndpoint.java
@@ -147,6 +147,14 @@ public class RemoteEndpoint
}
}
+ protected NotificationMessage createNotificationMessage(String method, Object parameter) {
+ NotificationMessage notificationMessage = new NotificationMessage();
+ notificationMessage.setJsonrpc(MessageConstants.JSONRPC_VERSION);
+ notificationMessage.setMethod(method);
+ notificationMessage.setParams(parameter);
+ return notificationMessage;
+ }
+
protected RequestMessage createRequestMessage(String method, Object parameter) {
RequestMessage requestMessage = new RequestMessage();
requestMessage.setId(String.valueOf(nextRequestId.incrementAndGet()));
@@ -161,14 +169,6 @@ public class RemoteEndpoint
notify(MessageJsonHandler.CANCEL_METHOD.getMethodName(), cancelParams);
}
- protected NotificationMessage createNotificationMessage(String method, Object parameter) {
- NotificationMessage notificationMessage = new NotificationMessage();
- notificationMessage.setJsonrpc(MessageConstants.JSONRPC_VERSION);
- notificationMessage.setMethod(method);
- notificationMessage.setParams(parameter);
- return notificationMessage;
- }
-
@Override
public void consume(Message message) {
if (message instanceof NotificationMessage) {
@@ -220,6 +220,20 @@ public class RemoteEndpoint
out.consume(createErrorResponseMessage(requestMessage, errorObject));
}
+ protected ResponseMessage createErrorResponseMessage(
+ RequestMessage requestMessage, ResponseError errorObject) {
+ ResponseMessage responseMessage = createResponseMessage(requestMessage);
+ responseMessage.setError(errorObject);
+ return responseMessage;
+ }
+
+ protected ResponseMessage createResponseMessage(RequestMessage requestMessage) {
+ ResponseMessage responseMessage = new ResponseMessage();
+ responseMessage.setRawId(requestMessage.getRawId());
+ responseMessage.setJsonrpc(MessageConstants.JSONRPC_VERSION);
+ return responseMessage;
+ }
+
protected void handleResponseIssues(ResponseMessage responseMessage, List issues) {
PendingRequestInfo requestInfo;
synchronized (sentRequestMap) {
@@ -242,20 +256,6 @@ public class RemoteEndpoint
}
}
- protected ResponseMessage createErrorResponseMessage(
- RequestMessage requestMessage, ResponseError errorObject) {
- ResponseMessage responseMessage = createResponseMessage(requestMessage);
- responseMessage.setError(errorObject);
- return responseMessage;
- }
-
- protected ResponseMessage createResponseMessage(RequestMessage requestMessage) {
- ResponseMessage responseMessage = new ResponseMessage();
- responseMessage.setRawId(requestMessage.getRawId());
- responseMessage.setJsonrpc(MessageConstants.JSONRPC_VERSION);
- return responseMessage;
- }
-
@Override
public String resolveMethod(String requestId) {
synchronized (sentRequestMap) {
diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/StandardLauncher.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/StandardLauncher.java
index e609a2ebb..17d20eca6 100644
--- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/StandardLauncher.java
+++ b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/StandardLauncher.java
@@ -11,12 +11,12 @@
******************************************************************************/
package org.eclipse.lsp4j.jsonrpc;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-
import org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor;
import org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
public class StandardLauncher implements Launcher {
private final ExecutorService execService;
private final T remoteProxy;
diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/JsonRpcMethod.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/JsonRpcMethod.java
index 52f424580..fd7cff027 100644
--- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/JsonRpcMethod.java
+++ b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/JsonRpcMethod.java
@@ -11,10 +11,10 @@
******************************************************************************/
package org.eclipse.lsp4j.jsonrpc.json;
-import java.lang.reflect.Type;
-
import com.google.gson.TypeAdapterFactory;
+import java.lang.reflect.Type;
+
/** A description of a JSON-RPC method. */
public class JsonRpcMethod {
@@ -38,6 +38,22 @@ public class JsonRpcMethod {
this.isNotification = isNotification;
}
+ public static JsonRpcMethod notification(String name, Type... parameterTypes) {
+ return new JsonRpcMethod(name, parameterTypes, Void.class, null, true);
+ }
+
+ public static JsonRpcMethod request(String name, Type returnType, Type... parameterTypes) {
+ return new JsonRpcMethod(name, parameterTypes, returnType, null, false);
+ }
+
+ public static JsonRpcMethod request(
+ String name,
+ Type returnType,
+ TypeAdapterFactory returnTypeAdapterFactory,
+ Type... parameterTypes) {
+ return new JsonRpcMethod(name, parameterTypes, returnType, returnTypeAdapterFactory, false);
+ }
+
public String getMethodName() {
return methodName;
}
@@ -58,22 +74,6 @@ public class JsonRpcMethod {
return isNotification;
}
- public static JsonRpcMethod notification(String name, Type... parameterTypes) {
- return new JsonRpcMethod(name, parameterTypes, Void.class, null, true);
- }
-
- public static JsonRpcMethod request(String name, Type returnType, Type... parameterTypes) {
- return new JsonRpcMethod(name, parameterTypes, returnType, null, false);
- }
-
- public static JsonRpcMethod request(
- String name,
- Type returnType,
- TypeAdapterFactory returnTypeAdapterFactory,
- Type... parameterTypes) {
- return new JsonRpcMethod(name, parameterTypes, returnType, returnTypeAdapterFactory, false);
- }
-
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/JsonRpcMethodProvider.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/JsonRpcMethodProvider.java
index 10b8ea944..5bbbbf944 100644
--- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/JsonRpcMethodProvider.java
+++ b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/JsonRpcMethodProvider.java
@@ -11,10 +11,10 @@
******************************************************************************/
package org.eclipse.lsp4j.jsonrpc.json;
-import java.util.Map;
-
import org.eclipse.lsp4j.jsonrpc.Endpoint;
+import java.util.Map;
+
/**
* Provides {@link JsonRpcMethod}. Can be implemented by {@link Endpoint}s to provide information
* about the supported methods.
diff --git a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageJsonHandler.java b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageJsonHandler.java
index 7f46098f6..5b071ab8c 100644
--- a/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageJsonHandler.java
+++ b/build-tools/jsonrpc/src/main/java/org/eclipse/lsp4j/jsonrpc/json/MessageJsonHandler.java
@@ -11,14 +11,13 @@
******************************************************************************/
package org.eclipse.lsp4j.jsonrpc.json;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.Collections;
-import java.util.Map;
-import java.util.function.Consumer;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonIOException;
+import com.google.gson.JsonParseException;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import com.google.gson.stream.MalformedJsonException;
import org.eclipse.lsp4j.jsonrpc.MessageIssueException;
import org.eclipse.lsp4j.jsonrpc.json.adapters.CollectionTypeAdapter;
@@ -32,24 +31,23 @@ import org.eclipse.lsp4j.jsonrpc.messages.Message;
import org.eclipse.lsp4j.jsonrpc.messages.MessageIssue;
import org.eclipse.lsp4j.jsonrpc.messages.ResponseErrorCode;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonIOException;
-import com.google.gson.JsonParseException;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonToken;
-import com.google.gson.stream.MalformedJsonException;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Collections;
+import java.util.Map;
+import java.util.function.Consumer;
/** A wrapper around Gson that includes configuration required for JSON-RPC messages. */
public class MessageJsonHandler {
public static final JsonRpcMethod CANCEL_METHOD =
JsonRpcMethod.notification("$/cancelRequest", CancelParams.class);
-
+ private static MessageJsonHandler toStringInstance;
private final Gson gson;
-
private final Map