Added events for preference change

This commit is contained in:
Akash Yadav
2022-07-14 17:51:52 +05:30
parent b5a020cf43
commit 8098ba0926
39 changed files with 275 additions and 231 deletions
@@ -1050,8 +1050,6 @@ public class EditorActivity extends StudioActivity
@Override
protected void onPause() {
super.onPause();
dispatchOnPauseToEditors();
EditorActivityActions.clear();
if (mFileTreeFragment != null) {
mFileTreeFragment.saveTreeState();
@@ -1089,18 +1087,6 @@ public class EditorActivity extends StudioActivity
});
}
private void dispatchOnPauseToEditors() {
CompletableFuture.runAsync(
() -> {
for (int i = 0; i < mViewModel.getOpenedFileCount(); i++) {
final var editor = getEditorAtIndex(i);
if (editor != null) {
editor.onPause();
}
}
});
}
@Override
protected void onSaveInstanceState(@NonNull final Bundle outState) {
outState.putString(KEY_PROJECT_PATH, ProjectManager.INSTANCE.getProjectDirPath());
@@ -19,7 +19,6 @@ package com.itsaky.androidide.handlers
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.itsaky.androidide.EditorActivity
import com.itsaky.androidide.eventbus.events.Event
import com.itsaky.androidide.eventbus.events.EventReceiver
import com.itsaky.androidide.eventbus.events.editor.OnCreateEvent
@@ -31,7 +30,10 @@ import com.itsaky.androidide.eventbus.events.editor.OnStopEvent
import com.itsaky.androidide.projects.FileManager
import com.itsaky.androidide.projects.ProjectManager
import com.itsaky.androidide.utils.BootClasspathProvider
import com.itsaky.androidide.utils.EditorActivityActions
import com.itsaky.androidide.utils.Environment
import java.util.concurrent.*
import org.greenrobot.eventbus.EventBus
/**
* Observes lifecycle events if [com.itsaky.androidide.EditorActivity].
@@ -41,32 +43,33 @@ import java.util.concurrent.*
class EditorActivityLifecyclerObserver : DefaultLifecycleObserver {
private val fileActionsHandler = FileTreeActionHandler()
override fun onCreate(owner: LifecycleOwner) {
dispatchEvent(OnCreateEvent())
}
override fun onStart(owner: LifecycleOwner) {
CompletableFuture.runAsync(BootClasspathProvider::init)
CompletableFuture.runAsync(this::initBootclasspathProvider)
register(fileActionsHandler, FileManager, ProjectManager)
dispatchEvent(OnStartEvent())
}
override fun onResume(owner: LifecycleOwner) {
dispatchEvent(OnResumeEvent())
}
override fun onPause(owner: LifecycleOwner) {
EditorActivityActions.clear()
dispatchEvent(OnPauseEvent())
}
override fun onStop(owner: LifecycleOwner) {
unregister(fileActionsHandler, FileManager, ProjectManager)
dispatchEvent(OnStopEvent())
}
override fun onDestroy(owner: LifecycleOwner) {
dispatchEvent(OnDestroyEvent())
}
@@ -79,5 +82,11 @@ class EditorActivityLifecyclerObserver : DefaultLifecycleObserver {
receivers.forEach { it.unregister() }
}
private fun dispatchEvent(event: Event) {}
private fun dispatchEvent(event: Event) {
EventBus.getDefault().post(event)
}
private fun initBootclasspathProvider() {
BootClasspathProvider.update(listOf(Environment.ANDROID_JAR.absolutePath))
}
}
@@ -388,10 +388,6 @@ public class CodeEditorView extends FrameLayout {
return binding.editor.getText().toString();
}
public void onPause() {
// unimplemented
}
public void onResume() {
configureEditorIfNeeded();
}
@@ -0,0 +1,36 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.eventbus.events.preferences
import com.itsaky.androidide.eventbus.events.Event
/**
* Dispatched when a preference's is value changed in IDE preferences.
*
* @param key The key of the preference that was changed.
* @param value The new value of the preference.
* @author Akash Yadav
*/
data class PreferenceChangeEvent(val key: String, val value: Any) : Event()
/**
* Dispatched when a preference is removed from shared preferences.
*
* @param key The key of the preference that was removed.
*/
data class PreferenceRemoveEvent(val key: String) : Event()
+1 -1
View File
@@ -48,7 +48,7 @@ dependencies {
api project (path: ':build-tools:eventbus-events')
api project (path: ':build-tools:tooling-api')
implementation project (path: ':common')
implementation project (path: ':shared')
implementation common.io
implementation google.guava
@@ -53,8 +53,8 @@ abstract class ModuleProject(
const val USAGE_RUNTIME = "java-runtime"
}
@JvmField val compileJavaSourceClasses = SourceClassTrie()
@JvmField val compileClasspathClasses = ClassTrie()
@JvmField val compileJavaSourceClasses = com.itsaky.androidide.utils.SourceClassTrie()
@JvmField val compileClasspathClasses = com.itsaky.androidide.utils.ClassTrie()
/**
* Get the source directories of this module (non-transitive i.e for this module only).
@@ -113,7 +113,7 @@ abstract class ModuleProject(
log.debug("Sources indexed for project: '$path'. Found $count source files.")
val paths = getCompileClasspaths().filter { it.exists() }
val topLevelClasses = ClasspathReader.listClasses(paths).filter { it.isTopLevel }
val topLevelClasses = com.itsaky.androidide.utils.ClasspathReader.listClasses(paths).filter { it.isTopLevel }
topLevelClasses.forEach { this.compileClasspathClasses.append(it.name) }
log.debug("Classpaths indexed for project: '$path'. Found ${topLevelClasses.size} classpaths.")
}
@@ -31,7 +31,7 @@ class ClassTrieTest {
@Test
fun testAppend() {
val trie = ClassTrie()
val trie = com.itsaky.androidide.utils.ClassTrie()
trie.append("java.lang.String")
trie.append("java.lang.String.Inner")
trie.append("java.lang.Object")
@@ -48,7 +48,7 @@ class ClassTrieTest {
@Test
fun testRemoval() {
val trie = ClassTrie()
val trie = com.itsaky.androidide.utils.ClassTrie()
trie.append("java.lang.String")
trie.append("java.lang.Object")
trie.append("java.util.List")
+3
View File
@@ -49,8 +49,11 @@ dependencies {
implementation androidx.ktx
implementation common.kotlin
implementation project (path: ':build-tools:eventbus-events')
api androidx.multidex
api project (path: ':shared')
api project (path: ':build-tools:logger')
testImplementation tests.junit
@@ -1,26 +1,30 @@
/************************************************************************************
* This file is part of AndroidIDE.
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*
**************************************************************************************/
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.managers;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import com.itsaky.androidide.eventbus.events.preferences.PreferenceChangeEvent;
import com.itsaky.androidide.eventbus.events.preferences.PreferenceRemoveEvent;
import org.greenrobot.eventbus.EventBus;
public class PreferenceManager {
public static final String KEY_IS_FIRST_PROJECT_BUILD = "project_isFirstBuild";
@@ -60,20 +64,35 @@ public class PreferenceManager {
public PreferenceManager remove(String key) {
prefs.edit().remove(key).apply();
dispatchRemoveEvent(key);
return this;
}
protected void dispatchRemoveEvent(final String key) {
EventBus.getDefault().post(new PreferenceRemoveEvent(key));
}
public PreferenceManager putInt(String key, int val) {
prefs.edit().putInt(key, val).apply();
dispatchChangeEvent(key, val);
return this;
}
protected void dispatchChangeEvent(final String key, final Object value) {
dispatchChangeEvent(new PreferenceChangeEvent(key, value));
}
protected void dispatchChangeEvent(final PreferenceChangeEvent event) {
EventBus.getDefault().post(event);
}
public int getInt(String key) {
return prefs.getInt(key, 0);
}
public PreferenceManager putFloat(String key, float val) {
prefs.edit().putFloat(key, val).apply();
dispatchChangeEvent(key, val);
return this;
}
@@ -107,6 +126,7 @@ public class PreferenceManager {
public PreferenceManager putString(String key, String value) {
prefs.edit().putString(key, value).apply();
dispatchChangeEvent(key, value);
return this;
}
@@ -132,6 +152,7 @@ public class PreferenceManager {
public PreferenceManager putBoolean(String key, boolean value) {
prefs.edit().putBoolean(key, value).apply();
dispatchChangeEvent(key, value);
return this;
}
@@ -1,43 +0,0 @@
/************************************************************************************
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*
**************************************************************************************/
package com.itsaky.androidide.managers;
import java.io.File;
import java.util.HashMap;
public class VersionedFileManager {
private static final HashMap<File, Integer> map = new HashMap<>();
public static int fileOpened(File file) {
// Initial version of file should always be 1
map.put(file, 1);
return 1;
}
public static int incrementVersion(File file) {
if (!map.containsKey(file)) {
map.put(file, 1);
}
int version = map.get(file);
version++;
map.put(file, version);
return version;
}
}
@@ -1,60 +0,0 @@
/************************************************************************************
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*
**************************************************************************************/
package com.itsaky.androidide.models;
import android.os.Parcel;
import android.os.Parcelable;
public class DexPair implements Parcelable {
public static final Creator<DexPair> CREATOR =
new Creator<DexPair>() {
@Override
public DexPair createFromParcel(Parcel p1) {
return new DexPair(p1);
}
@Override
public DexPair[] newArray(int p1) {
return new DexPair[p1];
}
};
public String first;
public String second;
private DexPair(Parcel in) {
first = in.readString();
second = in.readString();
}
public DexPair(String first, String second) {
this.first = first;
this.second = second;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel p1, int p2) {
p1.writeString(first);
p1.writeString(second);
}
}
@@ -1,63 +0,0 @@
/************************************************************************************
* This file is part of AndroidIDE.
*
*
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*
**************************************************************************************/
package com.itsaky.androidide.utils;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
/** Writes an InputStream to a file */
public class InputStreamWriter implements Runnable {
private final InputStream in;
private final File out;
private final BufferedOutputStream os;
public InputStreamWriter(InputStream in, File out) throws FileNotFoundException {
this.in = in;
this.out = out;
this.os = new BufferedOutputStream(new FileOutputStream(out, true));
}
@Override
public void run() {
try {
final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
while (true) {
final String data = reader.readLine();
if (data == null) {
break;
}
os.write(data.concat("\n").getBytes());
os.flush();
}
} catch (Throwable th) {
// ignored
}
}
}
@@ -32,7 +32,7 @@ class ClasspathReaderTest {
@Test
fun testListClasses() {
val classes =
ClasspathReader.listClasses(
com.itsaky.androidide.utils.ClasspathReader.listClasses(
listOf(File("../tests/test-project/app/src/main/resources/android.jar"))
)
@@ -33,7 +33,7 @@ class OrganizeImportsAction : BaseCodeAction() {
}
override fun execAction(data: ActionData): Any {
val watch = StopWatch("Organize imports")
val watch = com.itsaky.androidide.utils.StopWatch("Organize imports")
return try {
val editor = requireEditor(data)
val content = editor.text
@@ -32,7 +32,7 @@ class RemoveUnusedImportsAction : BaseCodeAction() {
}
override fun execAction(data: ActionData): Any {
val watch = StopWatch("Remove unused imports")
val watch = com.itsaky.androidide.utils.StopWatch("Remove unused imports")
return try {
val editor = requireEditor(data)
val content = editor.text
@@ -110,7 +110,7 @@ class GenerateConstructorAction : FieldBasedAction() {
return
}
val stopWatch = StopWatch("generateConstructorForFields()")
val stopWatch = com.itsaky.androidide.utils.StopWatch("generateConstructorForFields()")
val constructor =
newConstructor(type.simpleName.toString(), varTypes.toTypedArray(), varNames.toTypedArray())
val body = constructor.createBody()
@@ -209,7 +209,7 @@ class ImportCompletionProvider(
result.add(fromClasspath)
}
BootClasspathProvider.getAllEntries().forEach {
com.itsaky.androidide.utils.BootClasspathProvider.getAllEntries().forEach {
abortIfCancelled()
val fromBootclasspath = collectPackageNode(it, pkgName)
if (fromBootclasspath != null) {
@@ -228,7 +228,7 @@ class ImportCompletionProvider(
* @param pkgName The package name of the package to find node for.
* @return The found package name. Or `null` if no package can be found.
*/
private fun collectPackageNode(trie: ClassTrie, pkgName: String): Node? {
private fun collectPackageNode(trie: com.itsaky.androidide.utils.ClassTrie, pkgName: String): Node? {
val segments = trie.segments(pkgName)
var node: Node? = trie.root
for (segment in segments) {
@@ -347,7 +347,7 @@ class ImportCompletionProvider(
addDirectChildNodes(classpathNode, incomplete, list, names, packageOnly)
}
BootClasspathProvider.getAllEntries().forEach {
com.itsaky.androidide.utils.BootClasspathProvider.getAllEntries().forEach {
abortIfCancelled()
val node =
if (pkgName.isEmpty()) {
+1
View File
@@ -35,3 +35,4 @@ include ':build-tools:eventbus-events'
include ':build-tools:tooling-api-testing'
include ':build-tools:javac-services'
include ':lsp:models'
include ':shared'
+1
View File
@@ -0,0 +1 @@
/build
+41
View File
@@ -0,0 +1,41 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdkVersion rootProject.ext.compileSdk
buildToolsVersion rootProject.ext.buildTools
defaultConfig {
minSdkVersion rootProject.ext.minSdk
targetSdkVersion rootProject.ext.targetSdk
}
buildFeatures.viewBinding true
compileOptions {
sourceCompatibility rootProject.ext.javaSourceVersion
targetCompatibility rootProject.ext.javaTargetVersion
}
kotlinOptions {
jvmTarget = "11"
}
buildTypes {
release {
minifyEnabled true
}
}
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
dependencies {
implementation google.guava
implementation project(path: ':build-tools:logger')
}
View File
+21
View File
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
@@ -0,0 +1,41 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.shared
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.itsaky.androidide.shared.test", appContext.packageName)
}
}
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ This file is part of AndroidIDE.
~
~ AndroidIDE is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ AndroidIDE is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
-->
<manifest package="com.itsaky.androidide.shared"/>
@@ -35,11 +35,6 @@ public class BootClasspathProvider {
private static final Map<String, ClassTrie> bootClasspathClasses = new ConcurrentHashMap<>();
private static final ILogger LOG = ILogger.newInstance("BootClassProvider");
/** Initializes the classpath provider with the default boot classpath. */
public static synchronized void init() {
update(Collections.singleton(Environment.ANDROID_JAR.getAbsolutePath()));
}
/**
* Updates the boot classpath cache. If a classpath is already indexed, it is skipped.
*
@@ -17,8 +17,6 @@
package com.itsaky.androidide.utils
import androidx.core.text.isDigitsOnly
/**
* Information about a class in a JAR file.
*
@@ -68,5 +66,15 @@ private constructor(
return ClassInfo(name, simpleName, packageName, isTopLevel, isAnonymous, isLocal, isInner)
}
private fun CharSequence.isDigitsOnly(): Boolean {
for (char in this) {
if (!char.isDigit()) {
return false
}
}
return true
}
}
}
@@ -17,8 +17,6 @@
package com.itsaky.androidide.utils
import com.itsaky.androidide.utils.ILogger
/**
* A stop watch helps to log duration between the time when the instance of the stopwatch instance
* was created and the time when [StopWatch.log] or [StopWatch.lap] method is called.
@@ -48,4 +46,4 @@ class StopWatch(
log.debug("$message in ${System.currentTimeMillis() - lastLap}ms")
lastLap = System.currentTimeMillis()
}
}
}
@@ -0,0 +1,34 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itsaky.androidide.shared
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}
Binary file not shown.