diff --git a/tools/idea-plugin/CHANGELOG.md b/tools/idea-plugin/CHANGELOG.md index afac1139c..468705d1d 100644 --- a/tools/idea-plugin/CHANGELOG.md +++ b/tools/idea-plugin/CHANGELOG.md @@ -15,7 +15,8 @@ - [Web Import] Add `Ionicons` icons provider - [Web Import] Add `Tabler` icons provider - [Web Import] Add `Eva` icons provider -- Add "Suppress unused receiver warning" setting to generate `@Suppress("UnusedReceiverParameter")` annotation on +- [Settings] Add "Gutter area" toggle to control visibility of ImageVector gutter icons in the editor +- [Settings] Add "Suppress unused receiver warning" setting to generate `@Suppress("UnusedReceiverParameter")` annotation on ImageVector extension properties when an icon pack receiver is used (e.g. `ValkyrieIcons`) ### Changed diff --git a/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/gutter/ImageVectorGutterProvider.kt b/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/gutter/ImageVectorGutterProvider.kt index c859ab757..a41b4ce81 100644 --- a/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/gutter/ImageVectorGutterProvider.kt +++ b/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/gutter/ImageVectorGutterProvider.kt @@ -8,6 +8,7 @@ import com.intellij.pom.Navigatable import com.intellij.psi.PsiElement import com.intellij.psi.createSmartPointer import io.github.composegears.valkyrie.sdk.core.extensions.safeAs +import io.github.composegears.valkyrie.service.PersistentSettings.Companion.persistentSettings import io.github.composegears.valkyrie.util.getOrCreateGutterIcon import io.github.composegears.valkyrie.util.isImageVector import javax.swing.Icon @@ -22,6 +23,9 @@ class ImageVectorGutterProvider : LineMarkerProvider { elements: List, result: MutableCollection>, ) { + val psiElement = elements.firstOrNull { it != null } ?: return + if (!psiElement.project.persistentSettings.state.showImageVectorGutterIcon) return + // Process ImageVector property definitions elements.filterIsInstance() .filter { it.isImageVector() } diff --git a/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/service/PersistentSettings.kt b/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/service/PersistentSettings.kt index 9f2c2bc81..dc4e03a5e 100644 --- a/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/service/PersistentSettings.kt +++ b/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/service/PersistentSettings.kt @@ -55,6 +55,7 @@ class PersistentSettings : SimplePersistentStateComponent(Valkyri var showImageVectorPreview: Boolean by property(true) var showIconsInProjectView: Boolean by property(true) + var showImageVectorGutterIcon: Boolean by property(true) var indentSize: Int by property(4) // MaterialSymbols diff --git a/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/settings/InMemorySettings.kt b/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/settings/InMemorySettings.kt index c8b710f31..3fa697a9a 100644 --- a/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/settings/InMemorySettings.kt +++ b/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/settings/InMemorySettings.kt @@ -61,6 +61,7 @@ class InMemorySettings(project: Project) { suppressUnusedReceiverWarning = false showImageVectorPreview = true showIconsInProjectView = true + showImageVectorGutterIcon = true indentSize = 4 materialFontFill = DEFAULT_FILL materialFontWeight = DEFAULT_WEIGHT @@ -107,6 +108,7 @@ class InMemorySettings(project: Project) { suppressUnusedReceiverWarning = suppressUnusedReceiverWarning, showImageVectorPreview = showImageVectorPreview, showIconsInProjectView = showIconsInProjectView, + showImageVectorGutterIcon = showImageVectorGutterIcon, ) } } @@ -135,6 +137,7 @@ data class ValkyriesSettings( val showImageVectorPreview: Boolean, val showIconsInProjectView: Boolean, + val showImageVectorGutterIcon: Boolean, ) fun PersistentSettings.ValkyrieState.updateNestedPack(packs: List) { diff --git a/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/settings/SettingsViewModel.kt b/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/settings/SettingsViewModel.kt index c74335fb8..1a1bc5d98 100644 --- a/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/settings/SettingsViewModel.kt +++ b/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/settings/SettingsViewModel.kt @@ -14,6 +14,7 @@ import io.github.composegears.valkyrie.ui.screen.settings.model.SettingsAction.U import io.github.composegears.valkyrie.ui.screen.settings.model.SettingsAction.UpdateExplicitMode import io.github.composegears.valkyrie.ui.screen.settings.model.SettingsAction.UpdateFlatPackage import io.github.composegears.valkyrie.ui.screen.settings.model.SettingsAction.UpdateIconsInProjectView +import io.github.composegears.valkyrie.ui.screen.settings.model.SettingsAction.UpdateImageVectorGutterIcon import io.github.composegears.valkyrie.ui.screen.settings.model.SettingsAction.UpdateImageVectorPreview import io.github.composegears.valkyrie.ui.screen.settings.model.SettingsAction.UpdateIndentSize import io.github.composegears.valkyrie.ui.screen.settings.model.SettingsAction.UpdateOutputFormat @@ -54,6 +55,7 @@ class SettingsViewModel : ViewModel() { previewType = it.previewType, showImageVectorPreview = it.showImageVectorPreview, showIconsInProjectView = it.showIconsInProjectView, + showImageVectorGutterIcon = it.showImageVectorGutterIcon, ) } @@ -64,6 +66,7 @@ class SettingsViewModel : ViewModel() { is UpdateOutputFormat -> updateOutputFormat(settingsAction.outputFormat) is UpdateImageVectorPreview -> showImageVectorPreview = settingsAction.enabled is UpdateIconsInProjectView -> showIconsInProjectView = settingsAction.enabled + is UpdateImageVectorGutterIcon -> showImageVectorGutterIcon = settingsAction.enabled is UpdateFlatPackage -> flatPackage = settingsAction.useFlatPackage is UpdateExplicitMode -> useExplicitMode = settingsAction.useExplicitMode is UpdateAddTrailingComma -> addTrailingComma = settingsAction.addTrailingComma @@ -102,5 +105,6 @@ data class GeneralSettings( data class PreviewSettings( val showImageVectorPreview: Boolean, val showIconsInProjectView: Boolean, + val showImageVectorGutterIcon: Boolean, val previewType: PreviewType, ) diff --git a/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/settings/model/SettingsAction.kt b/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/settings/model/SettingsAction.kt index 1b86cc6a5..cb15a5c1f 100644 --- a/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/settings/model/SettingsAction.kt +++ b/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/settings/model/SettingsAction.kt @@ -16,5 +16,6 @@ sealed interface SettingsAction { data class UpdateImageVectorPreview(val enabled: Boolean) : SettingsAction data class UpdateIconsInProjectView(val enabled: Boolean) : SettingsAction + data class UpdateImageVectorGutterIcon(val enabled: Boolean) : SettingsAction data class UpdatePreviewType(val previewType: PreviewType) : SettingsAction } diff --git a/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/settings/tabs/preview/ImageVectorPreviewSettingsScreen.kt b/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/settings/tabs/preview/ImageVectorPreviewSettingsScreen.kt index a234c8cf9..c42c07599 100644 --- a/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/settings/tabs/preview/ImageVectorPreviewSettingsScreen.kt +++ b/tools/idea-plugin/src/main/kotlin/io/github/composegears/valkyrie/ui/screen/settings/tabs/preview/ImageVectorPreviewSettingsScreen.kt @@ -8,6 +8,8 @@ import androidx.compose.runtime.setValue import androidx.lifecycle.viewmodel.compose.viewModel import com.composegears.tiamat.compose.navController import com.composegears.tiamat.compose.navDestination +import com.intellij.openapi.application.ex.ApplicationManagerEx +import com.intellij.openapi.ui.MessageDialogBuilder import io.github.composegears.valkyrie.jewel.settings.CheckboxSettingsRow import io.github.composegears.valkyrie.jewel.settings.Group import io.github.composegears.valkyrie.jewel.settings.GroupSpacing @@ -18,11 +20,16 @@ import io.github.composegears.valkyrie.ui.screen.settings.PreviewSettings import io.github.composegears.valkyrie.ui.screen.settings.SettingsViewModel import io.github.composegears.valkyrie.ui.screen.settings.model.SettingsAction import io.github.composegears.valkyrie.ui.screen.settings.model.SettingsAction.UpdateIconsInProjectView +import io.github.composegears.valkyrie.ui.screen.settings.model.SettingsAction.UpdateImageVectorGutterIcon import io.github.composegears.valkyrie.ui.screen.settings.model.SettingsAction.UpdateImageVectorPreview import io.github.composegears.valkyrie.ui.screen.settings.model.SettingsAction.UpdatePreviewType import io.github.composegears.valkyrie.ui.screen.settings.tabs.preview.ui.PreviewBgSection +import io.github.composegears.valkyrie.util.ValkyrieBundle.message import io.github.composegears.valkyrie.util.stringResource +import java.awt.Component import org.jetbrains.compose.ui.tooling.preview.Preview +import org.jetbrains.jewel.foundation.ExperimentalJewelApi +import org.jetbrains.jewel.foundation.LocalComponent import org.jetbrains.jewel.ui.component.VerticallyScrollableContainer val ImageVectorPreviewSettingsScreen by navDestination { @@ -35,11 +42,14 @@ val ImageVectorPreviewSettingsScreen by navDestination { ) } +@OptIn(ExperimentalJewelApi::class) @Composable private fun ImageVectorPreviewSettingsUi( previewSettings: PreviewSettings, onAction: (SettingsAction) -> Unit, ) { + val component = LocalComponent.current + VerticallyScrollableContainer { Column { Group(text = stringResource("settings.imagevector.preview.ide.preview.header")) { @@ -47,13 +57,28 @@ private fun ImageVectorPreviewSettingsUi( text = stringResource("settings.imagevector.preview.ide.option.previewer"), infoText = stringResource("settings.imagevector.preview.ide.option.previewer.description"), checked = previewSettings.showImageVectorPreview, - onCheckedChange = { onAction(UpdateImageVectorPreview(it)) }, + onCheckedChange = { + onAction(UpdateImageVectorPreview(it)) + promptRestart(component) + }, ) CheckboxSettingsRow( text = stringResource("settings.imagevector.preview.ide.option.projectview"), infoText = stringResource("settings.imagevector.preview.ide.option.projectview.description"), checked = previewSettings.showIconsInProjectView, - onCheckedChange = { onAction(UpdateIconsInProjectView(it)) }, + onCheckedChange = { + onAction(UpdateIconsInProjectView(it)) + promptRestart(component) + }, + ) + CheckboxSettingsRow( + text = stringResource("settings.imagevector.preview.ide.option.guttericon"), + infoText = stringResource("settings.imagevector.preview.ide.option.guttericon.description"), + checked = previewSettings.showImageVectorGutterIcon, + onCheckedChange = { + onAction(UpdateImageVectorGutterIcon(it)) + promptRestart(component) + }, ) } GroupSpacing() @@ -66,23 +91,41 @@ private fun ImageVectorPreviewSettingsUi( } } +private fun promptRestart(component: Component) { + val shouldRestart = MessageDialogBuilder + .yesNo( + title = message("settings.restart.dialog.title"), + message = message("settings.restart.dialog.message"), + ) + .yesText(message("settings.restart.dialog.now")) + .noText(message("settings.restart.dialog.later")) + .ask(component) + + if (shouldRestart) { + ApplicationManagerEx.getApplicationEx().restart(true) + } +} + @Preview @Composable private fun ImageVectorPreviewSettingsPreview() = PreviewTheme { var showImageVectorPreview by rememberMutableState { true } var showIconsInProjectView by rememberMutableState { true } + var showImageVectorGutterIcon by rememberMutableState { true } var previewType by rememberMutableState { PreviewType.Auto } ImageVectorPreviewSettingsUi( previewSettings = PreviewSettings( showImageVectorPreview = showImageVectorPreview, showIconsInProjectView = showIconsInProjectView, + showImageVectorGutterIcon = showImageVectorGutterIcon, previewType = previewType, ), onAction = { when (it) { is UpdateImageVectorPreview -> showImageVectorPreview = it.enabled is UpdateIconsInProjectView -> showIconsInProjectView = it.enabled + is UpdateImageVectorGutterIcon -> showImageVectorGutterIcon = it.enabled is UpdatePreviewType -> previewType = it.previewType else -> {} } diff --git a/tools/idea-plugin/src/main/resources/messages/Valkyrie.properties b/tools/idea-plugin/src/main/resources/messages/Valkyrie.properties index ff016b474..95064c87c 100644 --- a/tools/idea-plugin/src/main/resources/messages/Valkyrie.properties +++ b/tools/idea-plugin/src/main/resources/messages/Valkyrie.properties @@ -104,11 +104,17 @@ settings.generator.preview.block=Add @Preview annotation settings.generator.preview.block.description=Note: This option is deprecated. Consider using the built-in ImageVector previewer instead settings.generator.indent=Indent size: settings.generator.indent.description=Determines the number of spaces used for each level of indentation in the imported icon -settings.imagevector.preview.ide.preview.header=IDE Icon Preview -settings.imagevector.preview.ide.option.previewer=Show ImageVector preview -settings.imagevector.preview.ide.option.previewer.description=Enable icon preview functionality in the IDE without @Preview annotation -settings.imagevector.preview.ide.option.projectview=Show icons in Project View -settings.imagevector.preview.ide.option.projectview.description=Display ImageVector preview as file icons in the project tree.\nTo ensure the icon cache updates fully, it's recommended to restart the IDE. +settings.imagevector.preview.ide.preview.header=IDE Integrations +settings.imagevector.preview.ide.option.previewer=Editor preview +settings.imagevector.preview.ide.option.previewer.description=Renders an interactive icon preview next to the file editor without requiring a @Preview annotation. +settings.imagevector.preview.ide.option.projectview=Project View +settings.imagevector.preview.ide.option.projectview.description=Displays ImageVector icons as file icons in the project tree. +settings.imagevector.preview.ide.option.guttericon=Gutter area +settings.imagevector.preview.ide.option.guttericon.description=Displays ImageVector icons as gutter icons next to property declarations in the editor. +settings.restart.dialog.title=Restart Required +settings.restart.dialog.message=Some changes require an IDE restart to take effect. Would you like to restart now? +settings.restart.dialog.now=Restart Now +settings.restart.dialog.later=Later settings.imagevector.preview.background.header=Preview background settings.imagevector.preview.background.black=Black settings.imagevector.preview.background.white=White