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 0641d75f5..b35023082 100644 --- a/app/src/main/java/com/itsaky/androidide/fragments/LogViewFragment.kt +++ b/app/src/main/java/com/itsaky/androidide/fragments/LogViewFragment.kt @@ -240,7 +240,7 @@ abstract class LogViewFragment : Fragment(), ShareableOutputFragment { } } - IDEColorSchemeProvider.readScheme(requireContext()) { scheme -> + IDEColorSchemeProvider.readScheme(requireContext(), LogLanguage.TS_TYPE) { scheme -> editor.applyTreeSitterLang(LogLanguage(requireContext()), LogLanguage.TS_TYPE, scheme) } } diff --git a/editor/src/main/java/com/itsaky/androidide/editor/language/treesitter/TreeSitterLanguage.kt b/editor/src/main/java/com/itsaky/androidide/editor/language/treesitter/TreeSitterLanguage.kt index 5e01da337..54eba9220 100644 --- a/editor/src/main/java/com/itsaky/androidide/editor/language/treesitter/TreeSitterLanguage.kt +++ b/editor/src/main/java/com/itsaky/androidide/editor/language/treesitter/TreeSitterLanguage.kt @@ -57,7 +57,7 @@ abstract class TreeSitterLanguage(context: Context, lang: TSLanguage, type: Stri init { this.languageSpec = getLanguageSpec(context, type, lang, newLocalCaptureSpec(type)) this.tsTheme = TsTheme(languageSpec.spec.tsQuery) - IDEColorSchemeProvider.readScheme(context) { scheme -> + IDEColorSchemeProvider.readScheme(context, type) { scheme -> if (scheme == null) { log.error("Failed to read color scheme") return@readScheme diff --git a/editor/src/main/java/com/itsaky/androidide/editor/schemes/IDEColorSchemeProvider.kt b/editor/src/main/java/com/itsaky/androidide/editor/schemes/IDEColorSchemeProvider.kt index bbcbff51e..34a3c5394 100644 --- a/editor/src/main/java/com/itsaky/androidide/editor/schemes/IDEColorSchemeProvider.kt +++ b/editor/src/main/java/com/itsaky/androidide/editor/schemes/IDEColorSchemeProvider.kt @@ -19,6 +19,7 @@ package com.itsaky.androidide.editor.schemes import android.content.Context import com.itsaky.androidide.eventbus.events.editor.ColorSchemeInvalidatedEvent +import com.itsaky.androidide.preferences.internal.DEFAULT_COLOR_SCHEME import com.itsaky.androidide.preferences.internal.colorScheme import com.itsaky.androidide.syntax.colorschemes.SchemeAndroidIDE import com.itsaky.androidide.tasks.executeAsyncProvideError @@ -45,26 +46,33 @@ object IDEColorSchemeProvider { private const val SCHEME_IS_DARK = "scheme.isDark" private const val SCHEME_FILE = "scheme.file" - var currentScheme: IDEColorScheme? = null + var defaultScheme: IDEColorScheme? = null get() { - if (field != null) { - return field - } - - val scheme = this.schemes[colorScheme] ?: return null - field = try { - scheme.load() - scheme.darkVariant?.load() - scheme - } catch (err: Exception) { - log.error("An error occurred while loading color scheme '$colorScheme'", err) - null - } - - return field + return field ?: getColorScheme(DEFAULT_COLOR_SCHEME).also { field = it } } private set + var currentScheme: IDEColorScheme? = null + get() { + return field ?: getColorScheme(colorScheme).also { field = it } + } + private set + + private fun getColorScheme(name: String): IDEColorScheme? { + return schemes[name]?.also(this::loadColorScheme) + } + + private fun loadColorScheme(scheme: IDEColorScheme): IDEColorScheme? { + return try { + scheme.load() + scheme.darkVariant?.load() + scheme + } catch (err: Exception) { + log.error("An error occurred while loading color scheme '$colorScheme'", err) + null + } + } + @JvmStatic fun init() { val schemeDirs = @@ -97,11 +105,11 @@ object IDEColorSchemeProvider { ) "" } - + if (version <= 0) { log.warn("Version code of color scheme '$schemeDir' must be set to >= 1") } - + if (file.isBlank()) { continue } @@ -112,12 +120,12 @@ object IDEColorSchemeProvider { scheme.isDarkScheme = isDark schemes[schemeDir.name] = scheme } - + schemes.values.forEach { it.darkVariant = schemes["${it.key}-dark"] } } - + @JvmStatic fun initIfNeeded() { if (this.schemes.isEmpty()) { @@ -125,19 +133,21 @@ object IDEColorSchemeProvider { } } - fun readScheme(context: Context, schemeConsumer: Consumer) { - readScheme(context) { + @JvmOverloads + fun readScheme(context: Context, type: String? = null, schemeConsumer: Consumer) { + readScheme(context, type) { schemeConsumer.accept(it) } } - fun readScheme(context: Context, consume: (SchemeAndroidIDE?) -> Unit) { - executeAsyncProvideError({ this.currentScheme }) { scheme, error -> + @JvmOverloads + fun readScheme(context: Context, type: String? = null, consume: (SchemeAndroidIDE?) -> Unit) { + executeAsyncProvideError({ getColorSchemeForType(type) }) { scheme, error -> if (scheme == null || error != null) { log.error("Failed to read color scheme", error) return@executeAsyncProvideError } - + val dark = scheme.darkVariant if (context.isSystemInDarkMode() && dark != null) { consume(dark) @@ -147,15 +157,32 @@ object IDEColorSchemeProvider { } } + fun getColorSchemeForType(type: String?) : IDEColorScheme? { + if (type == null) { + return currentScheme + } + + return currentScheme?.let { scheme -> + return@let if (scheme.getLanguageScheme(type) == null) { + log.warn("Color scheme '${scheme.name}' does not support '$type'") + log.warn("Falling back to default color scheme") + null + } else { + scheme + } + } ?: defaultScheme + } + fun list(): List { // filter out schemes that are dark variants of other schemes // schemes with both light and dark variant will be used according to system's dark mode return this.schemes.values.filter { !it.key.endsWith("-dark") }.toList() } - + fun destroy() { this.schemes.clear() this.currentScheme = null + this.defaultScheme = null } fun reload() { diff --git a/editor/src/main/java/com/itsaky/androidide/editor/schemes/LocalCaptureSpecProvider.kt b/editor/src/main/java/com/itsaky/androidide/editor/schemes/LocalCaptureSpecProvider.kt index 64e97b35d..14db526bc 100644 --- a/editor/src/main/java/com/itsaky/androidide/editor/schemes/LocalCaptureSpecProvider.kt +++ b/editor/src/main/java/com/itsaky/androidide/editor/schemes/LocalCaptureSpecProvider.kt @@ -32,7 +32,7 @@ object LocalCaptureSpecProvider { @JvmStatic fun newLocalCaptureSpec(type: String): LocalsCaptureSpec { val lang = - IDEColorSchemeProvider.currentScheme?.languages?.get(type) + IDEColorSchemeProvider.getColorSchemeForType(type)?.languages?.get(type) ?: run { log.error( "Cannot create LocalsCaptureSpec", diff --git a/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java b/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java index bcc3fc249..b3461354c 100644 --- a/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java +++ b/editor/src/main/java/com/itsaky/androidide/editor/ui/IDEEditor.java @@ -958,7 +958,7 @@ public class IDEEditor extends CodeEditor implements IEditor, ILspEditor { final var language = createLanguage(file); final var extension = FilesKt.getExtension(file); if (language instanceof TreeSitterLanguage) { - IDEColorSchemeProvider.INSTANCE.readScheme(getContext(), scheme -> { + IDEColorSchemeProvider.INSTANCE.readScheme(getContext(), extension, scheme -> { applyTreeSitterLang(language, extension, scheme); }); } else { diff --git a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/ShowXmlActivity.kt b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/ShowXmlActivity.kt index 7062494bb..1d5cbee17 100644 --- a/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/ShowXmlActivity.kt +++ b/uidesigner/src/main/java/com/itsaky/androidide/uidesigner/ShowXmlActivity.kt @@ -68,7 +68,7 @@ class ShowXmlActivity : BaseIDEActivity() { editor.setText(intent?.getStringExtra(KEY_XML) ?: "") editor.setTextSize(fontSize) - IDEColorSchemeProvider.readScheme(this) { + IDEColorSchemeProvider.readScheme(this, XMLLanguage.TS_TYPE) { if (it == null) { log.error("Unable to load color sheme") return@readScheme