diff --git a/CHANGELOG.md b/CHANGELOG.md index 80b2741..1da8aab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ ## [Unreleased] +## [1.3.1] - 2024-08-26 +### Changed +- Fix NullPointerException for Windows users. + + ## [1.3.0] - 2024-07-31 ### Changed - Add support of Sogou Pinyin Method (Chinese) for macOS. diff --git a/README.md b/README.md index 49b461f..77530a8 100644 --- a/README.md +++ b/README.md @@ -33,13 +33,6 @@ This feature is particularly beneficial for developers juggling multiple languag - **🌐 Supported Languages And Input Methods:** Supports multiple languages and input methods, including Sogou Pinyin Method (Chinese) for macOS. -## Installation -[Get from marketplace](https://plugins.jetbrains.com/plugin/22072-kursor) or install it directly inside your IDE: - -- **For Windows & Linux:** `File` > `Settings` > `Plugins` > `Marketplace` > Search for "Kursor" > `Install Plugin` > Restart IntelliJ IDEA -- **For Mac:** `IntelliJ IDEA` > `Preferences` > `Plugins` > `Marketplace` > Search for "Kursor" > `Install Plugin` > Restart IntelliJ IDEA - - ## Usage Once installed, Kursor will automatically run when you open your project in IntelliJ IDEA. @@ -79,5 +72,5 @@ Kursor is open-source and available under the [Apache 2.0 license](https://www.a ## Support -[![Buy Me A Coffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/ivan.seredkin) +[Buy Me A Coffee](https://www.buymeacoffee.com/ivan.seredkin) diff --git a/gradle.properties b/gradle.properties index d8cc731..01803c7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ pluginGroup = com.github.siropkin.kursor pluginName = Kursor pluginRepositoryUrl = https://github.com/siropkin/kursor # SemVer format -> https://semver.org -pluginVersion = 1.3.0 +pluginVersion = 1.3.1 # Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html pluginSinceBuild = 232 diff --git a/src/main/kotlin/com/github/siropkin/kursor/KeyboardLayoutInfo.kt b/src/main/kotlin/com/github/siropkin/kursor/KeyboardLayout.kt similarity index 62% rename from src/main/kotlin/com/github/siropkin/kursor/KeyboardLayoutInfo.kt rename to src/main/kotlin/com/github/siropkin/kursor/KeyboardLayout.kt index e2e3b3e..a152b06 100644 --- a/src/main/kotlin/com/github/siropkin/kursor/KeyboardLayoutInfo.kt +++ b/src/main/kotlin/com/github/siropkin/kursor/KeyboardLayout.kt @@ -12,7 +12,7 @@ import java.io.IOException private const val unknown = "unk" // https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-language-pack-default-values -private val windowsKeyboardLayoutMap = mapOf( +private val windowsKeyboardVariantMap = mapOf( "00000402" to "BG", "00000404" to "CH", "00000405" to "CZ", @@ -78,157 +78,33 @@ private val windowsKeyboardLayoutMap = mapOf( "00050408" to "GK" ) -// https://www.autoitscript.com/autoit3/docs/appendix/OSLangCodes.htm -private val windowsKeyboardCountryCodeMap = mapOf( - "0004" to "zh-CHS", - "0401" to "ar-SA", - "0402" to "bg-BG", - "0403" to "ca-ES", - "0404" to "zh-TW", - "0405" to "cs-CZ", - "0406" to "da-DK", - "0407" to "de-DE", - "0408" to "el-GR", - "0409" to "en-US", - "040A" to "es-ES", - "040B" to "fi-FI", - "040C" to "fr-FR", - "040D" to "he-IL", - "040E" to "hu-HU", - "040F" to "is-IS", - "0410" to "it-IT", - "0411" to "ja-JP", - "0412" to "ko-KR", - "0413" to "nl-NL", - "0414" to "nb-NO", - "0415" to "pl-PL", - "0416" to "pt-BR", - "0417" to "rm-CH", - "0418" to "ro-RO", - "0419" to "ru-RU", - "041A" to "hr-HR", - "041B" to "sk-SK", - "041C" to "sq-AL", - "041D" to "sv-SE", - "041E" to "th-TH", - "041F" to "tr-TR", - "0420" to "ur-PK", - "0421" to "id-ID", - "0422" to "uk-UA", - "0423" to "be-BY", - "0424" to "sl-SI", - "0425" to "et-EE", - "0426" to "lv-LV", - "0427" to "lt-LT", - "0428" to "tg-TJ", - "0429" to "fa-IR", - "042A" to "vi-VN", - "042B" to "hy-AM", - "042C" to "az-AZ", - "042D" to "eu-ES", - "042E" to "hsb-DE", - "042F" to "mk-MK", - "0432" to "tn-ZA", - "0434" to "xh-ZA", - "0435" to "zu-ZA", - "0436" to "af-ZA", - "0437" to "ka-GE", - "0438" to "fo-FO", - "0439" to "hi-IN", - "043A" to "mt-MT", - "043B" to "se-NO", - "043E" to "ms-MY", - "043F" to "kk-KZ", - "0440" to "ky-KG", - "0441" to "sw-KE", - "0442" to "tk-TM", - "0443" to "uz-UZ", - "0444" to "tt-RU", - "0445" to "bn-IN", - "0446" to "pa-IN", - "0447" to "gu-IN", - "0448" to "or-IN", - "0449" to "ta-IN", - "044A" to "te-IN", - "044B" to "kn-IN", - "044C" to "ml-IN", - "044D" to "as-IN", - "044E" to "mr-IN", - "044F" to "sa-IN", - "0450" to "mn-MN", - "0451" to "bo-CN", - "0452" to "cy-GB", - "0453" to "km-KH", - "0454" to "lo-LA", - "0456" to "gl-ES", - "0457" to "kok-IN", - "0459" to "sd-IN", - "045A" to "syr-SY", - "045B" to "si-LK", - "045C" to "chr-US", - "045D" to "iu-CA", - "045E" to "am-ET", - "0461" to "ne-NP", - "0462" to "fy-NL", - "0463" to "ps-AF", - "0464" to "fil-PH", - "0465" to "dv-MV", - "0468" to "ha-NG", - "046A" to "yo-NG", - "046B" to "quz-BO", - "046C" to "nso-ZA", - "046D" to "ba-RU", - "046E" to "lb-LU", - "046F" to "kl-GL", - "0470" to "ig-NG", - "0473" to "ti-ET", - "0475" to "haw-US", - "0478" to "ii-CN", - "047A" to "arn-CL", - "047C" to "moh-CA", - "047E" to "br-FR", - "0480" to "ug-CN", - "0481" to "mi-NZ", - "0482" to "oc-FR", - "0483" to "co-FR", - "0484" to "gsw-FR", - "0485" to "sah-RU", - "0486" to "quc-GT", - "0487" to "rw-RW", - "0488" to "wo-SN", - "048C" to "prs-AF", - "0491" to "gd-GB", - "0492" to "ku-IQ", - "0801" to "ar-IQ" -) - private val macKeyboardVariantMap = mapOf( "UserDefined_com.sogou.inputmethod.pinyin" to "ZH" // https://pinyin.sogou.com/mac ) -class KeyboardLayout(private val layout: String, private val country: String, private val language: String) { - override fun toString(): String = layout.lowercase().ifEmpty { +class KeyboardLayoutInfo(private val language: String, private val country: String, private val variant: String) { + override fun toString(): String = variant.lowercase().ifEmpty { country.lowercase().ifEmpty { language.lowercase() } } } -class KeyboardLayoutInfo { +class KeyboardLayout { private var linuxDistribution: String = System.getenv("DESKTOP_SESSION")?.lowercase() ?: "" private var linuxDesktopGroup: String = System.getenv("XDG_SESSION_TYPE")?.lowercase() ?: "" private var linuxNonUbuntuKeyboardLayouts: List = emptyList() - fun getLayout(): KeyboardLayout { + fun getInfo(): KeyboardLayoutInfo { return when { Platform.isLinux() -> getLinuxKeyboardLayout() - Platform.isWindows() -> getWindowsKeyboardLayout() Platform.isMac() -> getMacKeyboardLayout() - else -> KeyboardLayout(unknown, unknown, unknown) + Platform.isWindows() -> getWindowsKeyboardLayout() + else -> KeyboardLayoutInfo(unknown, unknown, unknown) } } - private fun getLinuxKeyboardLayout(): KeyboardLayout { + private fun getLinuxKeyboardLayout(): KeyboardLayoutInfo { // InputContext.getInstance().locale is not working on Linux: it always returns "en_US" // This is not the ideal solution because it involves executing a shell command to know the current keyboard layout // which might affect the performance. And we have different commands for different Linux distributions. @@ -240,15 +116,15 @@ class KeyboardLayoutInfo { .substringAfter("('xkb', '") .substringBefore("')") .split("+") - val country = split[0] val language = if (split.size > 1) split[1] else "" - return KeyboardLayout("", country, language) + val country = split[0] + return KeyboardLayoutInfo(language, country, "") } // FIXME: This command does not work on linuxDesktopGroup = "wayland", // see: https://github.com/siropkin/kursor/issues/3 if (linuxDesktopGroup == "wayland") { - return KeyboardLayout(unknown, unknown, unknown) + return KeyboardLayoutInfo(unknown, unknown, unknown) } if (linuxNonUbuntuKeyboardLayouts.isEmpty()) { @@ -299,34 +175,38 @@ class KeyboardLayoutInfo { // Additional check to avoid out-of-bounds exception if (linuxCurrentKeyboardLayoutIndex >= linuxNonUbuntuKeyboardLayouts.size) { - return KeyboardLayout(unknown, unknown, unknown) + return KeyboardLayoutInfo(unknown, unknown, unknown) } // This is a bad solution because it returns 0 if it's a default layout and 1 in other cases, // and if user has more than two layouts, we do not know which one is really on if (linuxNonUbuntuKeyboardLayouts.size > 2 && linuxCurrentKeyboardLayoutIndex > 0) { - return KeyboardLayout(unknown, unknown, unknown) + return KeyboardLayoutInfo(unknown, unknown, unknown) } val country = linuxNonUbuntuKeyboardLayouts[linuxCurrentKeyboardLayoutIndex] - return KeyboardLayout("", country, "") + return KeyboardLayoutInfo("", country, "") } - private fun getMacKeyboardLayout(): KeyboardLayout { + private fun getMacKeyboardLayout(): KeyboardLayoutInfo { val locale = InputContext.getInstance().locale - val layout = macKeyboardVariantMap[locale.variant] ?: "" // variant example for US: UserDefined_252 - return KeyboardLayout(layout, locale.country, locale.language) + val variant = macKeyboardVariantMap[locale.variant] ?: "" // variant example for US: UserDefined_252 + return KeyboardLayoutInfo(locale.language, locale.country, variant) } - private fun getWindowsKeyboardLayout(): KeyboardLayout { - // Standard "InputContext.getInstance().locale" does not work on Windows - // in case user set different keyboard layout (inputs) for one language + private fun getWindowsKeyboardLayout(): KeyboardLayoutInfo { + val locale = InputContext.getInstance().locale + // Standard locale object does not return correct info in case user set different keyboard inputs for one language // see: https://github.com/siropkin/kursor/issues/4 val user32 = User32.INSTANCE - val fgWindow: WinDef.HWND = user32.GetForegroundWindow() // Get the handle of the foreground window + val fgWindow: WinDef.HWND? = user32.GetForegroundWindow() // Get the handle of the foreground window + + if (fgWindow == null) { + return KeyboardLayoutInfo(locale.language, locale.country, "") + } + val threadId = user32.GetWindowThreadProcessId(fgWindow, null) // Get the thread ID of the foreground window val hkl: HKL = user32.GetKeyboardLayout(threadId) // Get the keyboard layout for the thread - // FIXME: It should be a better way how to convert pointer to string // hkl.pointer returns native@0x4090409: last 4 digits are language id, the rest is layout id val inputMethod = hkl.pointer.toString().split("@")[1] @@ -346,18 +226,8 @@ class KeyboardLayoutInfo { } } layoutId = layoutId.uppercase() - - val languageId = inputMethod.substring(inputMethod.length - 4, inputMethod.length).uppercase() - - val layout = windowsKeyboardLayoutMap[layoutId] ?: unknown - val countryCode = windowsKeyboardCountryCodeMap[languageId] ?: unknown - if (layout == unknown && countryCode == unknown) { - return KeyboardLayout(unknown, unknown, unknown) - } - val split = countryCode.split("-") - val language = split[0] - val country = if (split.size > 1) split[1] else "" - return KeyboardLayout(layout, country, language) + val variant = windowsKeyboardVariantMap[layoutId] ?: "" + return KeyboardLayoutInfo(locale.language, locale.country, variant) } private fun executeNativeCommand(command: Array): String { diff --git a/src/main/kotlin/com/github/siropkin/kursor/Kursor.kt b/src/main/kotlin/com/github/siropkin/kursor/Kursor.kt index c89a260..947ecac 100644 --- a/src/main/kotlin/com/github/siropkin/kursor/Kursor.kt +++ b/src/main/kotlin/com/github/siropkin/kursor/Kursor.kt @@ -18,9 +18,8 @@ object IndicatorPosition { const val BOTTOM = "bottom" } - class Kursor(private var editor: Editor): JComponent(), ComponentListener, CaretListener { - private val keyboardLayoutInfo = KeyboardLayoutInfo() + private val keyboardLayout = KeyboardLayout() init { editor.contentComponent.add(this) @@ -116,16 +115,16 @@ class Kursor(private var editor: Editor): JComponent(), ComponentListener, Caret val settings = getSettings() val isCapsLockOn = settings.indicateCapsLock && getIsCapsLockOn() - val keyboardLayout = keyboardLayoutInfo.getLayout() - var keyboardLayoutString = keyboardLayout.toString() - if (keyboardLayoutString.isEmpty()) { + val keyboardLayoutInfo = keyboardLayout.getInfo() + var keyboardLayoutStringInfo = keyboardLayoutInfo.toString() + if (keyboardLayoutStringInfo.isEmpty()) { return } val caret = getPrimaryCaret() var caretColor: Color? = null if (settings.changeColorOnNonDefaultLanguage) { - if (keyboardLayoutString != settings.defaultLanguage) { + if (keyboardLayoutStringInfo != settings.defaultLanguage) { caretColor = settings.colorOnNonDefaultLanguage } } @@ -134,37 +133,37 @@ class Kursor(private var editor: Editor): JComponent(), ComponentListener, Caret setCaretColor(caret, caretColor) } - if (!settings.showIndicator) { + if (!settings.showTextIndicator) { return } - val showIndicator = settings.indicateDefaultLanguage || isCapsLockOn || keyboardLayoutString.lowercase() != settings.defaultLanguage.lowercase() - if (!showIndicator) { + val showTextIndicator = settings.indicateDefaultLanguage || isCapsLockOn || keyboardLayoutStringInfo.lowercase() != settings.defaultLanguage.lowercase() + if (!showTextIndicator) { return } if (isCapsLockOn) { - keyboardLayoutString = keyboardLayoutString.uppercase() + keyboardLayoutStringInfo = keyboardLayoutStringInfo.uppercase() } val caretWidth = getCaretWidth(caret) val caretHeight = getCaretHeight(caret) val caretPosition = getCaretPosition(caret) - val indicatorOffsetX = caretWidth + settings.indicatorHorizontalOffset - val indicatorOffsetY = when (settings.indicatorVerticalPosition) { - IndicatorPosition.TOP -> (if (caret.visualPosition.line == 0) settings.indicatorFontSize else settings.indicatorFontSize / 2) - 1 - IndicatorPosition.MIDDLE -> caretHeight / 2 + settings.indicatorFontSize / 2 - 1 + val indicatorOffsetX = caretWidth + settings.textIndicatorHorizontalOffset + val indicatorOffsetY = when (settings.textIndicatorVerticalPosition) { + IndicatorPosition.TOP -> (if (caret.visualPosition.line == 0) settings.textIndicatorFontSize else settings.textIndicatorFontSize / 2) - 1 + IndicatorPosition.MIDDLE -> caretHeight / 2 + settings.textIndicatorFontSize / 2 - 1 IndicatorPosition.BOTTOM -> caretHeight + 3 else -> 0 } - g.font = Font(settings.indicatorFontName, settings.indicatorFontStyle, settings.indicatorFontSize) + g.font = Font(settings.textIndicatorFontName, settings.textIndicatorFontStyle, settings.textIndicatorFontSize) g.color = if (caretColor == null) { - getColorWithAlpha(getDefaultCaretColor()!!, settings.indicatorFontAlpha) + getColorWithAlpha(getDefaultCaretColor()!!, settings.textIndicatorFontAlpha) } else { - getColorWithAlpha(caretColor, settings.indicatorFontAlpha) + getColorWithAlpha(caretColor, settings.textIndicatorFontAlpha) } - g.drawString(keyboardLayoutString, caretPosition.x + indicatorOffsetX, caretPosition.y + indicatorOffsetY) + g.drawString(keyboardLayoutStringInfo, caretPosition.x + indicatorOffsetX, caretPosition.y + indicatorOffsetY) } } diff --git a/src/main/kotlin/com/github/siropkin/kursor/settings/KursorSettings.kt b/src/main/kotlin/com/github/siropkin/kursor/settings/KursorSettings.kt index 446622e..d671131 100644 --- a/src/main/kotlin/com/github/siropkin/kursor/settings/KursorSettings.kt +++ b/src/main/kotlin/com/github/siropkin/kursor/settings/KursorSettings.kt @@ -21,18 +21,18 @@ class KursorSettings : PersistentStateComponent { var changeColorOnNonDefaultLanguage: Boolean = true var colorOnNonDefaultLanguage: Color = Color(255, 140, 0) - var showIndicator: Boolean = true + var showTextIndicator: Boolean = true - var indicateCapsLock: Boolean = true - var indicateDefaultLanguage: Boolean = false + var textIndicatorFontName: String = EditorColorsManager.getInstance().globalScheme.editorFontName + var textIndicatorFontStyle: Int = Font.PLAIN + var textIndicatorFontSize: Int = 11 + var textIndicatorFontAlpha: Int = 180 - var indicatorFontName: String = EditorColorsManager.getInstance().globalScheme.editorFontName - var indicatorFontStyle: Int = Font.PLAIN - var indicatorFontSize: Int = 11 - var indicatorFontAlpha: Int = 180 + var textIndicatorVerticalPosition: String = IndicatorPosition.TOP + var textIndicatorHorizontalOffset: Int = 4 - var indicatorVerticalPosition: String = IndicatorPosition.TOP - var indicatorHorizontalOffset: Int = 4 + var indicateCapsLock: Boolean = true + var indicateDefaultLanguage: Boolean = false override fun getState(): KursorSettings { return this diff --git a/src/main/kotlin/com/github/siropkin/kursor/settings/KursorSettingsComponent.kt b/src/main/kotlin/com/github/siropkin/kursor/settings/KursorSettingsComponent.kt index 6e006b5..2c85543 100644 --- a/src/main/kotlin/com/github/siropkin/kursor/settings/KursorSettingsComponent.kt +++ b/src/main/kotlin/com/github/siropkin/kursor/settings/KursorSettingsComponent.kt @@ -1,21 +1,23 @@ package com.github.siropkin.kursor.settings import com.github.siropkin.kursor.IndicatorPosition -import com.github.siropkin.kursor.KeyboardLayoutInfo +import com.github.siropkin.kursor.KeyboardLayout import com.intellij.ui.ColorPanel import com.intellij.ui.components.JBCheckBox import com.intellij.ui.components.JBLabel import com.intellij.ui.components.JBTextField import com.intellij.util.ui.FormBuilder import com.intellij.openapi.ui.ComboBox +import com.intellij.util.ui.JBUI import java.awt.* import javax.swing.* + private const val LABEL_SPACING = 10 private const val COMPONENT_SPACING = 35 class KursorSettingsComponent { - private val keyboardLayoutInfo = KeyboardLayoutInfo() + private val keyboardLayout = KeyboardLayout() private val defaultLanguageComponent = JBTextField("", 5) private val detectKeyboardLayoutButton = JButton("Detect Keyboard Layout") @@ -23,17 +25,17 @@ class KursorSettingsComponent { private val changeColorOnNonDefaultLanguageComponent = JBCheckBox("Change color on non-default language") private val colorOnNonDefaultLanguageComponent = ColorPanel() - private val showIndicatorComponent = JBCheckBox("Show text indicator") + private val showTextIndicatorComponent = JBCheckBox("Show text indicator") private val indicateCapsLockComponent = JBCheckBox("Indicate 'Caps Lock'") private val indicateDefaultLanguageComponent = JBCheckBox("Show default language") - private val indicatorFontNameComponent = ComboBox(GraphicsEnvironment.getLocalGraphicsEnvironment().availableFontFamilyNames) - private val indicatorFontStyleComponent = ComboBox(arrayOf(Font.PLAIN.toString(), Font.BOLD.toString(), Font.ITALIC.toString())) - private val indicatorFontSizeComponent = JBTextField() - private val indicatorFontAlphaComponent = JBTextField() + private val textIndicatorFontNameComponent = ComboBox(GraphicsEnvironment.getLocalGraphicsEnvironment().availableFontFamilyNames) + private val textIndicatorFontStyleComponent = ComboBox(arrayOf(Font.PLAIN.toString(), Font.BOLD.toString(), Font.ITALIC.toString())) + private val textIndicatorFontSizeComponent = JBTextField() + private val textIndicatorFontAlphaComponent = JBTextField() - private val indicatorVerticalPositionComponent = ComboBox(arrayOf(IndicatorPosition.TOP, IndicatorPosition.MIDDLE, IndicatorPosition.BOTTOM)) - private val indicatorHorizontalOffsetComponent = JBTextField() + private val textIndicatorVerticalPositionComponent = ComboBox(arrayOf(IndicatorPosition.TOP, IndicatorPosition.MIDDLE, IndicatorPosition.BOTTOM)) + private val textIndicatorHorizontalOffsetComponent = JBTextField() var panel: JPanel = FormBuilder.createFormBuilder() .addComponent(createLanguagePanel()) @@ -66,10 +68,10 @@ class KursorSettingsComponent { } } - var showIndicator: Boolean - get() = showIndicatorComponent.isSelected + var showTextIndicator: Boolean + get() = showTextIndicatorComponent.isSelected set(value) { - showIndicatorComponent.isSelected = value + showTextIndicatorComponent.isSelected = value } var indicateCapsLock: Boolean @@ -84,52 +86,52 @@ class KursorSettingsComponent { indicateDefaultLanguageComponent.isSelected = value } - var indicatorFontName: String - get() = indicatorFontNameComponent.selectedItem as String + var textIndicatorFontName: String + get() = textIndicatorFontNameComponent.selectedItem as String set(value) { - indicatorFontNameComponent.selectedItem = value + textIndicatorFontNameComponent.selectedItem = value } - var indicatorFontStyle: Int - get() = (indicatorFontStyleComponent.selectedItem as String).toInt() + var textIndicatorFontStyle: Int + get() = (textIndicatorFontStyleComponent.selectedItem as String).toInt() set(value) { - indicatorFontStyleComponent.selectedItem = value.toString() + textIndicatorFontStyleComponent.selectedItem = value.toString() } - var indicatorFontSize: Int - get() = indicatorFontSizeComponent.text.toInt() + var textIndicatorFontSize: Int + get() = textIndicatorFontSizeComponent.text.toInt() set(value) { try { val intValue = Integer.parseInt(value.toString()) - indicatorFontSizeComponent.text = intValue.coerceAtLeast(5).coerceAtMost(20).toString() + textIndicatorFontSizeComponent.text = intValue.coerceAtLeast(5).coerceAtMost(20).toString() } catch (_: NumberFormatException) { // indicatorFontSizeComponent.text = "" } } - var indicatorFontAlpha: Int - get() = indicatorFontAlphaComponent.text.toInt() + var textIndicatorFontAlpha: Int + get() = textIndicatorFontAlphaComponent.text.toInt() set(value) { try { val intValue = Integer.parseInt(value.toString()) - indicatorFontAlphaComponent.text = intValue.coerceAtLeast(0).coerceAtMost(255).toString() + textIndicatorFontAlphaComponent.text = intValue.coerceAtLeast(0).coerceAtMost(255).toString() } catch (_: NumberFormatException) { // indicatorFontAlphaComponent.text = "" } } - var indicatorVerticalPosition: String - get() = indicatorVerticalPositionComponent.selectedItem as String + var textIndicatorVerticalPosition: String + get() = textIndicatorVerticalPositionComponent.selectedItem as String set(value) { - indicatorVerticalPositionComponent.selectedItem = value + textIndicatorVerticalPositionComponent.selectedItem = value } - var indicatorHorizontalOffset: Int - get() = indicatorHorizontalOffsetComponent.text.toInt() + var textIndicatorHorizontalOffset: Int + get() = textIndicatorHorizontalOffsetComponent.text.toInt() set(value) { try { val intValue = Integer.parseInt(value.toString()) - indicatorHorizontalOffsetComponent.text = intValue.coerceAtLeast(-10).coerceAtMost(10).toString() + textIndicatorHorizontalOffsetComponent.text = intValue.coerceAtLeast(-10).coerceAtMost(10).toString() } catch (_: NumberFormatException) { // indicatorHorizontalOffsetComponent.text = "" } @@ -143,7 +145,7 @@ class KursorSettingsComponent { languagePanel.add(detectKeyboardLayoutButton, createRbc(2, 0, 1.0, COMPONENT_SPACING)) detectKeyboardLayoutButton.addActionListener { - defaultLanguageComponent.text = keyboardLayoutInfo.getLayout().toString() + defaultLanguageComponent.text = keyboardLayout.getInfo().toString() } return languagePanel @@ -165,28 +167,28 @@ class KursorSettingsComponent { private fun createIndicatorPanel(): JPanel { val checkBoxPanel = JPanel() checkBoxPanel.layout = GridBagLayout() - checkBoxPanel.add(showIndicatorComponent, createRbc(0, 0, 0.0)) + checkBoxPanel.add(showTextIndicatorComponent, createRbc(0, 0, 0.0)) checkBoxPanel.add(indicateDefaultLanguageComponent, createRbc(1, 0, 0.0, COMPONENT_SPACING)) checkBoxPanel.add(indicateCapsLockComponent, createRbc(2, 0, 1.0, COMPONENT_SPACING)) val fontPanel = JPanel() fontPanel.layout = GridBagLayout() fontPanel.add(JBLabel("Font:"), createRbc(0, 0, 0.0)) - fontPanel.add(indicatorFontNameComponent, createRbc(1, 0, 0.0, LABEL_SPACING)) + fontPanel.add(textIndicatorFontNameComponent, createRbc(1, 0, 0.0, LABEL_SPACING)) fontPanel.add(JBLabel("Size:"), createRbc(2, 0, 0.0, COMPONENT_SPACING)) - fontPanel.add(indicatorFontSizeComponent, createRbc(3, 0, 0.0, LABEL_SPACING)) + fontPanel.add(textIndicatorFontSizeComponent, createRbc(3, 0, 0.0, LABEL_SPACING)) fontPanel.add(JBLabel("Opacity:"), createRbc(4, 0, 0.0, COMPONENT_SPACING)) - fontPanel.add(indicatorFontAlphaComponent, createRbc(5, 0, 1.0, LABEL_SPACING)) - - showIndicatorComponent.addChangeListener { - indicateDefaultLanguageComponent.isEnabled = showIndicator - indicateCapsLockComponent.isEnabled = showIndicator - indicatorFontNameComponent.isEnabled = showIndicator - indicatorFontStyleComponent.isEnabled = showIndicator - indicatorFontSizeComponent.isEnabled = showIndicator - indicatorFontAlphaComponent.isEnabled = showIndicator - indicatorVerticalPositionComponent.isEnabled = showIndicator - indicatorHorizontalOffsetComponent.isEnabled = showIndicator + fontPanel.add(textIndicatorFontAlphaComponent, createRbc(5, 0, 1.0, LABEL_SPACING)) + + showTextIndicatorComponent.addChangeListener { + indicateDefaultLanguageComponent.isEnabled = showTextIndicator + indicateCapsLockComponent.isEnabled = showTextIndicator + textIndicatorFontNameComponent.isEnabled = showTextIndicator + textIndicatorFontStyleComponent.isEnabled = showTextIndicator + textIndicatorFontSizeComponent.isEnabled = showTextIndicator + textIndicatorFontAlphaComponent.isEnabled = showTextIndicator + textIndicatorVerticalPositionComponent.isEnabled = showTextIndicator + textIndicatorHorizontalOffsetComponent.isEnabled = showTextIndicator } val container = JPanel() @@ -201,12 +203,12 @@ class KursorSettingsComponent { val positionPanel = JPanel() positionPanel.layout = GridBagLayout() positionPanel.add(JBLabel("Vertical position:"), createRbc(0, 0, 0.0)) - positionPanel.add(indicatorVerticalPositionComponent, createRbc(1, 0, 0.0, LABEL_SPACING)) + positionPanel.add(textIndicatorVerticalPositionComponent, createRbc(1, 0, 0.0, LABEL_SPACING)) positionPanel.add(JBLabel("Horizontal offset:"), createRbc(2, 0, 0.0, COMPONENT_SPACING)) - positionPanel.add(indicatorHorizontalOffsetComponent, createRbc(3, 0, 1.0, LABEL_SPACING)) + positionPanel.add(textIndicatorHorizontalOffsetComponent, createRbc(3, 0, 1.0, LABEL_SPACING)) - indicatorVerticalPositionComponent.maximumSize = Dimension(200, indicatorVerticalPositionComponent.preferredSize.height) - indicatorHorizontalOffsetComponent.maximumSize = Dimension(100, indicatorHorizontalOffsetComponent.preferredSize.height) + textIndicatorVerticalPositionComponent.maximumSize = Dimension(200, textIndicatorVerticalPositionComponent.preferredSize.height) + textIndicatorHorizontalOffsetComponent.maximumSize = Dimension(100, textIndicatorHorizontalOffsetComponent.preferredSize.height) return positionPanel } @@ -227,7 +229,7 @@ class KursorSettingsComponent { gbc.weightx = weightx gbc.weighty = 1.0 - gbc.insets = Insets(10, paddingLeft ?: 0, 0, 0) + gbc.insets = JBUI.insets(10, paddingLeft ?: 0, 0, 0) return gbc } } diff --git a/src/main/kotlin/com/github/siropkin/kursor/settings/KursorSettingsConfigurable.kt b/src/main/kotlin/com/github/siropkin/kursor/settings/KursorSettingsConfigurable.kt index 546a37a..da0fef9 100644 --- a/src/main/kotlin/com/github/siropkin/kursor/settings/KursorSettingsConfigurable.kt +++ b/src/main/kotlin/com/github/siropkin/kursor/settings/KursorSettingsConfigurable.kt @@ -26,15 +26,15 @@ class KursorSettingsConfigurable: Configurable { return it.defaultLanguage != settings.defaultLanguage || it.changeColorOnNonDefaultLanguage != settings.changeColorOnNonDefaultLanguage || it.colorOnNonDefaultLanguage != settings.colorOnNonDefaultLanguage - || it.showIndicator != settings.showIndicator + || it.showTextIndicator != settings.showTextIndicator || it.indicateCapsLock != settings.indicateCapsLock || it.indicateDefaultLanguage != settings.indicateDefaultLanguage - || it.indicatorFontName != settings.indicatorFontName - || it.indicatorFontStyle != settings.indicatorFontStyle - || it.indicatorFontSize != settings.indicatorFontSize - || it.indicatorFontAlpha != settings.indicatorFontAlpha - || it.indicatorVerticalPosition != settings.indicatorVerticalPosition - || it.indicatorHorizontalOffset != settings.indicatorHorizontalOffset + || it.textIndicatorFontName != settings.textIndicatorFontName + || it.textIndicatorFontStyle != settings.textIndicatorFontStyle + || it.textIndicatorFontSize != settings.textIndicatorFontSize + || it.textIndicatorFontAlpha != settings.textIndicatorFontAlpha + || it.textIndicatorVerticalPosition != settings.textIndicatorVerticalPosition + || it.textIndicatorHorizontalOffset != settings.textIndicatorHorizontalOffset } return false } @@ -44,15 +44,15 @@ class KursorSettingsConfigurable: Configurable { settings.defaultLanguage = settingsComponent!!.defaultLanguage settings.changeColorOnNonDefaultLanguage = settingsComponent!!.changeColorOnNonDefaultLanguage settings.colorOnNonDefaultLanguage = settingsComponent!!.colorOnNonDefaultLanguage!! - settings.showIndicator = settingsComponent!!.showIndicator + settings.showTextIndicator = settingsComponent!!.showTextIndicator settings.indicateCapsLock = settingsComponent!!.indicateCapsLock settings.indicateDefaultLanguage = settingsComponent!!.indicateDefaultLanguage - settings.indicatorFontName = settingsComponent!!.indicatorFontName - settings.indicatorFontStyle = settingsComponent!!.indicatorFontStyle - settings.indicatorFontSize = settingsComponent!!.indicatorFontSize - settings.indicatorFontAlpha = settingsComponent!!.indicatorFontAlpha - settings.indicatorVerticalPosition = settingsComponent!!.indicatorVerticalPosition - settings.indicatorHorizontalOffset = settingsComponent!!.indicatorHorizontalOffset + settings.textIndicatorFontName = settingsComponent!!.textIndicatorFontName + settings.textIndicatorFontStyle = settingsComponent!!.textIndicatorFontStyle + settings.textIndicatorFontSize = settingsComponent!!.textIndicatorFontSize + settings.textIndicatorFontAlpha = settingsComponent!!.textIndicatorFontAlpha + settings.textIndicatorVerticalPosition = settingsComponent!!.textIndicatorVerticalPosition + settings.textIndicatorHorizontalOffset = settingsComponent!!.textIndicatorHorizontalOffset } override fun reset() { @@ -61,15 +61,15 @@ class KursorSettingsConfigurable: Configurable { it.defaultLanguage = settings.defaultLanguage it.changeColorOnNonDefaultLanguage = settings.changeColorOnNonDefaultLanguage it.colorOnNonDefaultLanguage = settings.colorOnNonDefaultLanguage - it.showIndicator = settings.showIndicator + it.showTextIndicator = settings.showTextIndicator it.indicateCapsLock = settings.indicateCapsLock it.indicateDefaultLanguage = settings.indicateDefaultLanguage - it.indicatorFontName = settings.indicatorFontName - it.indicatorFontStyle = settings.indicatorFontStyle - it.indicatorFontSize = settings.indicatorFontSize - it.indicatorFontAlpha = settings.indicatorFontAlpha - it.indicatorVerticalPosition = settings.indicatorVerticalPosition - it.indicatorHorizontalOffset = settings.indicatorHorizontalOffset + it.textIndicatorFontName = settings.textIndicatorFontName + it.textIndicatorFontStyle = settings.textIndicatorFontStyle + it.textIndicatorFontSize = settings.textIndicatorFontSize + it.textIndicatorFontAlpha = settings.textIndicatorFontAlpha + it.textIndicatorVerticalPosition = settings.textIndicatorVerticalPosition + it.textIndicatorHorizontalOffset = settings.textIndicatorHorizontalOffset } } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 7765013..73212f6 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -3,80 +3,6 @@ Kursor Ivan Seredkin - - Kursor simplifies language tracking directly on your IntelliJ IDE.
- It dynamically displays the current keyboard language on your cursor, offering the added functionality of changing the cursor's color to match the language in use.
- This feature is particularly beneficial for developers juggling multiple languages, significantly reducing the likelihood of typing errors. - ]]>
- - - ++++++++++++++++++
- Changed:
- - Add support of Sogou Pinyin Method (Chinese) for macOS.
-
- For Contributors and Developers:
- - Migrate from Gradle IntelliJ Plugin 1.x to 2.0.
-
-
- 1.2.0 (2024-07-29)
- ++++++++++++++++++
- Changed:
- - Plugin settings moved to Tools: `File` > `Settings` > `Tools` > `Kursor`.
- - Fix German keyboard layout abbreviation for Windows.
-
-
- 1.1.1 (2024-07-25)
- ++++++++++++++++++
- Changed:
- - Improved keyboard layout detection for Windows users, including detection of different input methods within the same language. Previously, Kursor would not detect different input methods within one language, but now it does.
-
-
- 1.1.0 (2024-07-19)
- ++++++++++++++++++
- Changed:
- - Improved keyboard layout detection across different operating systems, ensuring more accurate language tracking.
- - Transitioned the "Default Language" setting from a ComboBox component to an Input component, allowing for custom default language input and enhancing flexibility beyond pre-filled options.
- - - Added "Detect Keyboard Layout" button to the settings page, enabling users to manually detect their keyboard layout and update the default language accordingly.
-
- For Contributors and Developers:
- - Updated Gradle to version 8.9 to align with the latest development practices and ensure compatibility.
-
-
- 1.0.5 (2023-12-07)
- ++++++++++++++++++
- - Unspecify `pluginUntilBuild` (include all future builds)
-
-
- 1.0.4 (2023-10-25)
- ++++++++++++++++++
- - Improve MacOS support
-
-
- 1.0.3 (2023-07-28)
- ++++++++++++++++++
- - Improve Linux support
-
-
- 1.0.2 (2023-07-27)
- ++++++++++++++++++
- - Update `pluginUntilBuild` to include `232.*` (2023.2.*)
-
-
- 1.0.1 (2023-07-13)
- ++++++++++++++++++
-
- - Added Linux support.
- - Turning "Show default language" off by default
-
-
- 1.0.0 (2023-06-16)
- ++++++++++++++++++
-
- - Initial release. - ]]>
- com.intellij.modules.platform