[pycharm] PY-79603 Debugger: add threshold settings to combobox

(cherry picked from commit f7ab66227b511278fb924d42821aebdeacc4a034)

GitOrigin-RevId: 4f205bf426a676ff42e3f61847193c999a5aafb0
This commit is contained in:
ekaterina.itsenko
2025-03-06 13:53:37 +01:00
committed by intellij-monorepo-bot
parent b8fcb72733
commit 71679d03e6
3 changed files with 67 additions and 46 deletions

View File

@@ -95,4 +95,5 @@ image.color.mode.grayscale.image=Grayscale
image.color.mode.binarize.image=Binarized
image.binarize.dialog.title=Set Threshold
image.binarize.dialog.message=Please enter a valid integer between 0 and 255.
image.binarize.dialog.invalid=Invalid Input
image.binarize.dialog.invalid=Invalid Input
image.color.mode.configure.actions=Configure...

View File

@@ -7,15 +7,12 @@ import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.vfs.writeBytes
import org.intellij.images.ImagesBundle
import org.intellij.images.editor.ImageDocument
import org.intellij.images.scientific.ScientificUtils
import org.intellij.images.scientific.BinarizationThresholdConfig
import org.intellij.images.scientific.ScientificUtils
import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import javax.imageio.ImageIO
import javax.swing.JOptionPane
import javax.swing.JTextField
class BinarizeImageAction : AnAction() {
@@ -26,16 +23,8 @@ class BinarizeImageAction : AnAction() {
val imageFile = e.getData(CommonDataKeys.VIRTUAL_FILE) ?: return
val originalImage = imageFile.getUserData(ScientificUtils.ORIGINAL_IMAGE_KEY) ?: return
val thresholdConfig = ApplicationManager.getApplication().getService(BinarizationThresholdConfig::class.java) ?: return
val currentThreshold = thresholdConfig.threshold
val newThreshold = showThresholdDialog(e.project, currentThreshold)
if (newThreshold != null) {
thresholdConfig.threshold = newThreshold
}
else {
return
}
val byteArrayOutputStream = ByteArrayOutputStream()
val binarizedImage = applyBinarization(originalImage, newThreshold)
val binarizedImage = applyBinarization(originalImage, thresholdConfig.threshold)
ImageIO.write(binarizedImage, ScientificUtils.DEFAULT_IMAGE_FORMAT, byteArrayOutputStream)
imageFile.writeBytes(byteArrayOutputStream.toByteArray())
val document = e.getData(ImageDocument.IMAGE_DOCUMENT_DATA_KEY) ?: return
@@ -65,33 +54,4 @@ class BinarizeImageAction : AnAction() {
}
return binarizedImage
}
private fun showThresholdDialog(project: com.intellij.openapi.project.Project?, initialValue: Int): Int? {
val inputField = JTextField(initialValue.toString())
val optionPane = JOptionPane(
inputField,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION
)
val dialog = optionPane.createDialog(null, ImagesBundle.message("image.binarize.dialog.title"))
dialog.isAlwaysOnTop = true
dialog.isVisible = true
if (optionPane.value == JOptionPane.OK_OPTION) {
val threshold = inputField.text.toIntOrNull()
if (threshold != null && threshold in 0..255) {
return threshold
}
else {
JOptionPane.showMessageDialog(
null,
ImagesBundle.message("image.binarize.dialog.message"),
ImagesBundle.message("image.binarize.dialog.invalid"),
JOptionPane.ERROR_MESSAGE
)
return showThresholdDialog(project, initialValue)
}
}
return null
}
}

View File

@@ -3,11 +3,13 @@ package org.intellij.images.scientific.action
import com.intellij.openapi.actionSystem.*
import com.intellij.openapi.actionSystem.ex.CustomComponentAction
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.ui.ComboBox
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.openapi.util.registry.Registry
import org.intellij.images.ImagesBundle
import org.intellij.images.scientific.BinarizationThresholdConfig
import org.intellij.images.scientific.ScientificUtils
import java.awt.FlowLayout
import javax.swing.*
@@ -15,6 +17,7 @@ import javax.swing.*
class ImageOperationsActionGroup : DefaultActionGroup(), CustomComponentAction, DumbAware {
private var selectedMode: String = ORIGINAL_IMAGE
private val availableModes = listOf(ORIGINAL_IMAGE, INVERTED_IMAGE, GRAYSCALE_IMAGE, BINARIZE_IMAGE)
private val CONFIGURE_ACTIONS = ImagesBundle.message("image.color.mode.configure.actions")
init {
templatePresentation.apply {
@@ -48,12 +51,19 @@ class ImageOperationsActionGroup : DefaultActionGroup(), CustomComponentAction,
override fun createCustomComponent(presentation: Presentation, place: String): JComponent {
selectedMode = ORIGINAL_IMAGE
val comboBox = ComboBox(DefaultComboBoxModel(availableModes.toTypedArray())).apply {
val comboBox = ComboBox(DefaultComboBoxModel((availableModes + CONFIGURE_ACTIONS).toTypedArray())).apply {
selectedItem = selectedMode
isOpaque = false
addActionListener {
selectedMode = selectedItem as String
triggerModeAction(selectedMode)
val selectedItem = selectedItem as String
if (selectedItem == CONFIGURE_ACTIONS) {
openConfigurationDialog()
this.selectedItem = selectedMode
}
else {
selectedMode = selectedItem
triggerModeAction(selectedMode)
}
}
}
return JPanel(FlowLayout(FlowLayout.CENTER, 0, 0)).apply {
@@ -69,6 +79,18 @@ class ImageOperationsActionGroup : DefaultActionGroup(), CustomComponentAction,
actionGroup.add(InvertChannelsAction())
actionGroup.add(GrayscaleImageAction())
actionGroup.add(BinarizeImageAction())
actionGroup.addSeparator()
actionGroup.add(object : AnAction(CONFIGURE_ACTIONS) {
override fun actionPerformed(e: AnActionEvent) {
openConfigurationDialog()
}
override fun update(e: AnActionEvent) {
e.presentation.isEnabledAndVisible = true
}
})
return actionGroup
}
@@ -82,6 +104,44 @@ class ImageOperationsActionGroup : DefaultActionGroup(), CustomComponentAction,
}
}
private fun openConfigurationDialog() {
val thresholdConfig = ApplicationManager.getApplication().getService(BinarizationThresholdConfig::class.java) ?: return
val currentThreshold = thresholdConfig.threshold
val newThreshold = showThresholdDialog(currentThreshold)
if (newThreshold != null) {
thresholdConfig.threshold = newThreshold
}
}
private fun showThresholdDialog(initialValue: Int): Int? {
val inputField = JTextField(initialValue.toString())
val optionPane = JOptionPane(
inputField,
JOptionPane.PLAIN_MESSAGE,
JOptionPane.OK_CANCEL_OPTION
)
val dialog = optionPane.createDialog(null, ImagesBundle.message("image.binarize.dialog.title"))
dialog.isAlwaysOnTop = true
dialog.isVisible = true
if (optionPane.value == JOptionPane.OK_OPTION) {
val threshold = inputField.text.toIntOrNull()
if (threshold != null && threshold in 0..255) {
return threshold
}
else {
JOptionPane.showMessageDialog(
null,
ImagesBundle.message("image.binarize.dialog.message"),
ImagesBundle.message("image.binarize.dialog.invalid"),
JOptionPane.ERROR_MESSAGE
)
return showThresholdDialog(initialValue)
}
}
return null
}
companion object {
private val ORIGINAL_IMAGE: String = ImagesBundle.message("image.color.mode.original.image")
private val INVERTED_IMAGE: String = ImagesBundle.message("image.color.mode.inverted.image")