From 8fbc212297c898d96ef09ea0fefcf5f0ffa97e17 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Sun, 9 Jun 2019 16:27:07 +0200 Subject: [PATCH] introduce two type of listeners: instant and for final selections to avoid flooding of Undo stack in text editors GitOrigin-RevId: db577f0b97f3a4cf56cb5605a063b55ca5c4d4f3 --- .../src/com/intellij/ui/ColorPicker.java | 8 ++--- .../ui/colorpicker/ColorPickerBuilder.kt | 18 ++++++++--- .../ui/colorpicker/ColorPickerModel.kt | 32 +++++++++++++++++-- .../ui/colorpicker/LightCalloutPopup.kt | 5 ++- 4 files changed, 48 insertions(+), 15 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/ColorPicker.java b/platform/platform-impl/src/com/intellij/ui/ColorPicker.java index e25bb59ba59d..43fcd8d84610 100644 --- a/platform/platform-impl/src/com/intellij/ui/ColorPicker.java +++ b/platform/platform-impl/src/com/intellij/ui/ColorPicker.java @@ -355,21 +355,19 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen } public static void showColorPickerPopup(@Nullable Color currentColor, @NotNull ColorListener listener) { - LightCalloutPopup dialog = new LightCalloutPopup(); - - JPanel panel = new ColorPickerBuilder() + LightCalloutPopup popup = new ColorPickerBuilder() .setOriginalColor(currentColor) .addSaturationBrightnessComponent() .addColorAdjustPanel(new MaterialGraphicalColorPipetteProvider()) .addColorValuePanel().withFocus() //.addSeparator() //.addCustomComponent(MaterialColorPaletteProvider.INSTANCE) - .addColorListener(listener) + .addColorListener(listener, false) .focusWhenDisplay(true) .setFocusCycleRoot(true) .build(); - dialog.show(panel, null, MouseInfo.getPointerInfo().getLocation()); + popup.show(MouseInfo.getPointerInfo().getLocation()); } private JComponent buildTopPanel(boolean enablePipette) throws ParseException { diff --git a/platform/platform-impl/src/com/intellij/ui/colorpicker/ColorPickerBuilder.kt b/platform/platform-impl/src/com/intellij/ui/colorpicker/ColorPickerBuilder.kt index 6fe119cb1e18..5b606f793e94 100644 --- a/platform/platform-impl/src/com/intellij/ui/colorpicker/ColorPickerBuilder.kt +++ b/platform/platform-impl/src/com/intellij/ui/colorpicker/ColorPickerBuilder.kt @@ -48,7 +48,7 @@ class ColorPickerBuilder { private var focusCycleRoot = false private var focusedComponentIndex = -1 private val actionMap = mutableMapOf() - private val colorListeners = mutableListOf() + private val colorListeners = mutableListOf() fun setOriginalColor(originalColor: Color?) = apply { this.originalColor = originalColor } @@ -112,9 +112,13 @@ class ColorPickerBuilder { fun addKeyAction(keyStroke: KeyStroke, action: Action) = apply { actionMap[keyStroke] = action } - fun addColorListener(colorListener: ColorListener) = apply { colorListeners.add(colorListener) } + fun addColorListener(colorListener: ColorListener) = addColorListener(colorListener, true) - fun build(): JPanel { + fun addColorListener(colorListener: ColorListener, invokeOnEveryColorChange: Boolean) = apply { + colorListeners.add(ColorListenerInfo(colorListener, invokeOnEveryColorChange)) + } + + fun build(): LightCalloutPopup { if (componentsToBuild.isEmpty()) { throw IllegalStateException("The Color Picker should have at least one picking component.") } @@ -158,12 +162,16 @@ class ColorPickerBuilder { panel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(keyStroke, key) } - colorListeners.forEach { model.addListener(it) } + colorListeners.forEach { model.addListener(it.colorListener, it.invokeOnEveryColorChange) } - return panel + return LightCalloutPopup(panel, + closedCallback = { model.onClose() }, + cancelCallBack = { model.onCancel() }) } } private class MyFocusTraversalPolicy(val defaultComponent: Component?) : LayoutFocusTraversalPolicy() { override fun getDefaultComponent(aContainer: Container?): Component? = defaultComponent } + +private data class ColorListenerInfo(val colorListener: ColorListener, val invokeOnEveryColorChange: Boolean) diff --git a/platform/platform-impl/src/com/intellij/ui/colorpicker/ColorPickerModel.kt b/platform/platform-impl/src/com/intellij/ui/colorpicker/ColorPickerModel.kt index b78ca1f76dd0..bbdf94242dab 100644 --- a/platform/platform-impl/src/com/intellij/ui/colorpicker/ColorPickerModel.kt +++ b/platform/platform-impl/src/com/intellij/ui/colorpicker/ColorPickerModel.kt @@ -15,6 +15,7 @@ */ package com.intellij.ui.colorpicker +import com.intellij.openapi.application.ApplicationManager import com.intellij.ui.picker.ColorListener import java.awt.Color @@ -23,6 +24,7 @@ val DEFAULT_PICKER_COLOR = Color(0xFF, 0xFF, 0xFF, 0xFF) class ColorPickerModel(originalColor: Color = DEFAULT_PICKER_COLOR) { private val listeners = mutableSetOf() + private val instantListeners = mutableSetOf() var color: Color = originalColor private set @@ -31,6 +33,22 @@ class ColorPickerModel(originalColor: Color = DEFAULT_PICKER_COLOR) { color = newColor Color.RGBtoHSB(color.red, color.green, color.blue, hsb) + instantListeners.forEach { it.colorChanged(color, source) } + } + + fun onClose() { + ApplicationManager.getApplication().invokeLater { + listeners.forEach { it.colorChanged(color, this) } + } + } + + fun onCancel() { + //todo[kb] at the moment there is no any good way to close the color picker popup. Cancel outside triggers onCancel + onClose() + } + + fun applyColorToSource(newColor: Color, source: Any? = null) { + setColor(newColor, source) listeners.forEach { it.colorChanged(color, source) } } @@ -52,7 +70,17 @@ class ColorPickerModel(originalColor: Color = DEFAULT_PICKER_COLOR) { val brightness get() = hsb[2] - fun addListener(listener: ColorListener) = listeners.add(listener) + fun addListener(listener: ColorListener) = addListener(listener, true) - fun removeListener(listener: ColorListener) = listeners.remove(listener) + fun addListener(listener: ColorListener, invokeOnEveryColorChange: Boolean) { + listeners.add(listener) + if (invokeOnEveryColorChange) { + instantListeners.add(listener) + } + } + + fun removeListener(listener: ColorListener) { + listeners.remove(listener) + instantListeners.remove(listener) + } } diff --git a/platform/platform-impl/src/com/intellij/ui/colorpicker/LightCalloutPopup.kt b/platform/platform-impl/src/com/intellij/ui/colorpicker/LightCalloutPopup.kt index 5d398979d123..0e70e9e438e8 100644 --- a/platform/platform-impl/src/com/intellij/ui/colorpicker/LightCalloutPopup.kt +++ b/platform/platform-impl/src/com/intellij/ui/colorpicker/LightCalloutPopup.kt @@ -33,7 +33,7 @@ import javax.swing.JComponent * * The popup is automatically dismissed when the user clicks outside. */ -class LightCalloutPopup( +class LightCalloutPopup(val content: JComponent, val closedCallback: (() -> Unit)? = null, val cancelCallBack: (() -> Unit)? = null, val beforeShownCallback: (() -> Unit)? = null @@ -50,8 +50,7 @@ class LightCalloutPopup( */ @JvmOverloads fun show( - content: JComponent, - parentComponent: JComponent?, + parentComponent: JComponent? = null, location: Point, position: Balloon.Position = Balloon.Position.below ) {