[DBE-23393] Added table heatmap coloring to DataGrip

Merge-request: IJ-MR-165372
Merged-by: Anvar Ramazanov <anvar.ramazanov@jetbrains.com>

(cherry picked from commit 9e8bd85a80dcf8ac319559af40af0ca3aeba9f13)

IJ-MR-167231

GitOrigin-RevId: 62fa8f59ab384db634f50579ab552928c515335e
This commit is contained in:
Anvar Ramazanov
2025-06-24 19:43:18 +00:00
committed by intellij-monorepo-bot
parent 73c5e818bc
commit 0e416b3d97
14 changed files with 569 additions and 2 deletions

View File

@@ -403,4 +403,18 @@ action.Console.TableResult.SaveLobAsAction.AmbiguousQueryResult.text=ambiguous q
action.Console.TableResult.LoadFullCellAction.Confirmation.title=Warning
action.Console.TableResult.LoadFullCellAction.Confirmation.text=One of the loaded cells contains a large amount of data, which may affect performance. Do you want to continue?
data.loaders.waiting=Waiting for the loaders to be ready
data.loaders.plugin.ad.notification=Get loader for the file ''{0}''
data.loaders.plugin.ad.notification=Get loader for the file ''{0}''
# Different coloring modes from TableHeatmapColorLayer.ColoringMode enum.
datagrid.coloring.mode.off=Off
datagrid.coloring.mode.sequential=Sequential
datagrid.coloring.mode.diverging=Diverging
# Action group controlling the table heatmap-coloring mode.
group.TableViewColoringGroup.text=Table Coloring Options
action.ToggleTableViewColoringModeOffAction.text=Off
action.ToggleTableViewColoringModeSequentialAction.text=Sequential
action.ToggleTableViewColoringModeDivergingAction.text=Diverging
action.ToggleTableViewColorPerColumnAction.text=Each Column Independently
action.ToggleTableViewColorPerTableAction.text=Whole Table
action.ToggleTableViewColorBooleanColumnsAction.text=Color Boolean Columns
separator.TableViewColoring.mode=Table Color Mapping
separator.TableViewColoring.options=Options

View File

@@ -1,6 +1,7 @@
package com.intellij.database.extractors;
import com.intellij.database.datagrid.*;
import com.intellij.database.run.ui.DataAccessType;
import com.intellij.database.run.ui.grid.editors.GridCellEditorHelper;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.CommonClassNames;
@@ -182,6 +183,10 @@ public class ObjectFormatterUtil {
CommonClassNames.JAVA_LANG_BOOLEAN.equals(className)) && ((JdbcGridColumn)column).getSize() <= 1;
}
public static boolean isBooleanCell(@NotNull CoreGrid<GridRow, GridColumn> grid, @NotNull ModelIndex<GridRow> row, @NotNull ModelIndex<GridColumn> column) {
return isBooleanColumn(Objects.requireNonNull(grid.getDataModel(DataAccessType.DATABASE_DATA).getColumn(column)), GridCellEditorHelper.get(grid).guessJdbcTypeForEditing(grid, row, column));
}
public static boolean isNumericCell(@NotNull CoreGrid<GridRow, GridColumn> grid, @NotNull ModelIndex<GridRow> row, @NotNull ModelIndex<GridColumn> column) {
return isNumericValue(GridCellEditorHelper.get(grid).guessJdbcTypeForEditing(grid, row, column));
}

View File

@@ -331,6 +331,23 @@
icon="com.intellij.grid.core.impl.icons.GridCoreImplIcons.ColumnFilter" />
<action id="Console.TableResult.ToggleRecordView" class="com.intellij.database.actions.ToggleEditMaximizedViewAction"
icon="com.intellij.grid.core.impl.icons.GridCoreImplIcons.SingleRecordView"/>
<group id="TableViewColoringGroup" icon="com.intellij.grid.core.impl.icons.GridCoreImplIcons.TableHeatmap" popup="true">
<separator key="separator.TableViewColoring.mode"/>
<action id="ToggleTableViewColoringModeOffAction"
class="com.intellij.database.run.actions.ToggleTableViewColoringModeOffAction"/>
<action id="ToggleTableViewColoringModeSequentialAction"
class="com.intellij.database.run.actions.ToggleTableViewColoringModeSequentialAction"/>
<action id="ToggleTableViewColoringModeDivergingAction"
class="com.intellij.database.run.actions.ToggleTableViewColoringModeDivergingAction"/>
<separator key="separator.TableViewColoring.options"/>
<action id="ToggleTableViewColorPerColumnAction"
class="com.intellij.database.run.actions.ToggleTableViewColorPerColumnAction"/>
<action id="ToggleTableViewColorPerTableAction"
class="com.intellij.database.run.actions.ToggleTableViewColorPerTableAction"/>
<separator/>
<action id="ToggleTableViewColorBooleanColumnsAction"
class="com.intellij.database.run.actions.ToggleTableViewColorBooleanColumnsAction"/>
</group>
</group>
<reference ref="Console.TableResult.ChooseExtractor"/>
<group id="Console.TableResult.ChooseExtractor.Group">

View File

@@ -0,0 +1,66 @@
package com.intellij.database.datagrid.color
import java.awt.Color
/**
* Inspired by [java.awt.MultipleGradientPaintContext]
* Used for getting multiple gradient values.
* <pre>{@code
* @Suppress("UseJBColor")
* val multipleGradient by lazy { MultipleGradient(floatArrayOf(0f, 0.5f, 1f), arrayOf(Color.BLUE, Color.ORANGE, Color.RED)) }
*
* fun foo() {
* multipleGradient.getColor(0.3f)
* }
* }</pre>
*/
class MultipleGradient(private val fractions: FloatArray, colors: Array<Color>) {
private var normalizedIntervals = Array(fractions.size - 1) { index ->
fractions[index + 1] - fractions[index]
}
private var gradients = Array(normalizedIntervals.size){ index ->
interpolate(colors[index].rgb, colors[index + 1].rgb)
}
/** Position should be in range [0,1] or will be truncated to this range. */
fun getColor(position: Float): Color {
val pos = position.coerceIn(0f, 1f)
for (i in gradients.indices) {
if (pos < fractions[i + 1]) {
val delta = pos - fractions[i]
val index = ((delta / normalizedIntervals[i]) * GRADIENT_SIZE_INDEX).toInt()
return gradients[i][index]
}
}
return gradients[gradients.size - 1][GRADIENT_SIZE_INDEX]
}
private fun interpolate(rgb1: Int, rgb2: Int) : Array<Color> {
val a1 = rgb1 shr 24 and 0xff
val r1 = rgb1 shr 16 and 0xff
val g1 = rgb1 shr 8 and 0xff
val b1 = rgb1 and 0xff
val da = ((rgb2 shr 24) and 0xff) - a1
val dr = ((rgb2 shr 16) and 0xff) - r1
val dg = ((rgb2 shr 8) and 0xff) - g1
val db = ((rgb2) and 0xff) - b1
val stepSize = 1.0f / GRADIENT_SIZE
return Array(GRADIENT_SIZE) { i ->
val intColor = ((((a1 + i * da * stepSize) + 0.5).toInt() shl 24)) or
((((r1 + i * dr * stepSize) + 0.5).toInt() shl 16)) or
((((g1 + i * dg * stepSize) + 0.5).toInt() shl 8)) or ((((b1 + i * db * stepSize) + 0.5).toInt()))
@Suppress("UseJBColor") // Gradient is theme-aware.
Color(intColor)
}
}
companion object {
const val GRADIENT_SIZE: Int = 256
const val GRADIENT_SIZE_INDEX: Int = GRADIENT_SIZE - 1
}
}

View File

@@ -0,0 +1,280 @@
package com.intellij.database.datagrid.color
import com.intellij.database.DataGridBundle
import com.intellij.database.datagrid.DataGrid
import com.intellij.database.datagrid.GridColumn
import com.intellij.database.datagrid.GridModel
import com.intellij.database.datagrid.GridRequestSource
import com.intellij.database.datagrid.GridRow
import com.intellij.database.datagrid.ModelIndex
import com.intellij.database.datagrid.ModelIndexSet
import com.intellij.database.datagrid.mutating.ColumnDescriptor
import com.intellij.database.extractors.ObjectFormatterUtil
import com.intellij.database.run.ui.DataAccessType
import com.intellij.database.run.ui.table.TableResultView
import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.Disposable
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.Key
import com.intellij.ui.JBColor
import java.awt.Color
import kotlin.math.roundToInt
/**
* Adds and controls table heatmap-styled coloring.
*
* Usage: {code}TableHeatmapColorLayer.installOn(dataGrid){code}
*/
class TableHeatmapColorLayer private constructor(private val dataGrid: DataGrid, private val tableResultView: TableResultView, private val useOldColors: Boolean) : ColorLayer, GridModel.Listener<GridRow, GridColumn>, Disposable {
enum class ColoringMode(val title: String) {
OFF(DataGridBundle.message("datagrid.coloring.mode.off")),
SEQUENTIAL(DataGridBundle.message("datagrid.coloring.mode.sequential")),
DIVERGING(DataGridBundle.message("datagrid.coloring.mode.diverging"));
companion object {
fun getByName(name: String?) : ColoringMode = entries.firstOrNull { it.name == name } ?: DIVERGING
}
}
private class ColumnRange(val min: Double, val max: Double)
private val columns = mutableMapOf<ModelIndex<GridColumn>, ColumnRange>()
private var globalMax = -Double.MAX_VALUE
private var globalMin = Double.MAX_VALUE
var coloringMode: ColoringMode = getColoringMode()
set(value) {
if (field != value) {
field = value
setColoringMode(value)
tableResultView.showHorizontalLines = value != ColoringMode.OFF
tableResultView.repaint()
}
}
/** When true, the coloring separate for every numeric column, when false, the coloring is global. */
var perColumn : Boolean = isPerColumnColoringEnabled()
set(value) {
if (field != value) {
field = value
tableResultView.repaint()
}
}
var colorBooleanColumns: Boolean = isColorBooleanColumnsEnabled()
set(value) {
if (field != value) {
field = value
tableResultView.repaint()
}
}
init {
dataGrid.getDataModel(DataAccessType.DATA_WITH_MUTATIONS).addListener(this, this)
updateRanges()
}
override fun dispose(): Unit = Unit
override fun columnsAdded(columns: ModelIndexSet<GridColumn>?): Unit = Unit
override fun columnsRemoved(columns: ModelIndexSet<GridColumn>?): Unit = Unit
override fun rowsAdded(rows: ModelIndexSet<GridRow>?): Unit = Unit
override fun rowsRemoved(rows: ModelIndexSet<GridRow>?): Unit = Unit
override fun cellsUpdated(
rows: ModelIndexSet<GridRow>?,
columns: ModelIndexSet<GridColumn>?,
place: GridRequestSource.RequestPlace?,
): Unit = Unit
override fun afterLastRowAdded(): Unit = updateRanges()
private fun updateRanges() {
val dataModel = dataGrid.getDataModel(DataAccessType.DATA_WITH_MUTATIONS)
if (dataModel.rowCount == 0 || dataModel.columnCount == 0) {
return
}
dataModel.columnIndices.asIterable().forEach { columnIndex ->
val column = dataModel.getColumn(columnIndex)
val firstRow = dataModel.rowIndices.first()
// ColumnDescriptor.Attribute.HIGHLIGHTED currently is the only normal way do extract index column from coloring.
if (column == null ||
column.attributes.contains(ColumnDescriptor.Attribute.HIGHLIGHTED) ||
!ObjectFormatterUtil.isNumericCell(dataGrid, firstRow, columnIndex)) {
return@forEach
}
var min = Double.MAX_VALUE
var max = -Double.MAX_VALUE
dataModel.rowIndices.asIterable().forEach { rowIndex ->
val value = dataModel.getValueAt(rowIndex, columnIndex).toString().toDoubleOrNull()
if (value != null) {
if (min > value) min = value
if (max < value) max = value
}
}
if (max > globalMax) globalMax = max
if (min < globalMin) globalMin = min
if (min != Double.MAX_VALUE && max != -Double.MAX_VALUE) {
columns[columnIndex] = ColumnRange(min, max)
}
}
}
private fun getColor(x: Double, minX: Double, maxX: Double): Color? {
if (minX == maxX) return null // Protection from the situation with one-row table or column of same values.
val p = (x - minX) / (maxX - minX)
return when (coloringMode) { // Currently, this is white to blue.
ColoringMode.SEQUENTIAL -> {
//if (JBColor.isBright())
// Color.getHSBColor(240 / 360f, p.toFloat() * 0.6f, 1f)
//else
// Color.getHSBColor(240 / 360f, 220 / 360f, p.toFloat() * 0.7f)
if (JBColor.isBright())
getSimpleGradientLight(useOldColors).getColor(p.toFloat())
else
getSimpleGradientDark(useOldColors).getColor(p.toFloat())
}
// Multiple color gradient orange - blue - red.
ColoringMode.DIVERGING -> {
if (JBColor.isBright())
getMultipleGradientLight(useOldColors).getColor(p.toFloat())
else
getMultipleGradientDark(useOldColors).getColor(p.toFloat())
}
// Should not be called, but we will return our legacy colors for now.
else -> {
@Suppress("UseJBColor") if (JBColor.isBright()) Color((255 * p).roundToInt(), 0, (255 * (1 - p)).roundToInt(), 255).brighter()
else Color((255 * p).roundToInt(), 0, (255 * (1 - p)).roundToInt(), 255)
}
}
}
override fun getCellBackground(row: ModelIndex<GridRow>, column: ModelIndex<GridColumn>, grid: DataGrid, color: Color?): Color? {
if (coloringMode == ColoringMode.OFF) return null
val dataModel = dataGrid.getDataModel(DataAccessType.DATA_WITH_MUTATIONS)
if (colorBooleanColumns && ObjectFormatterUtil.isBooleanCell(grid, row, column)) {
return if (dataModel.getValueAt(row, column).toString().lowercase() == "true") {
getColor(0.6, 0.0, 1.0)
}
else {
getColor(0.0, 0.0, 1.0)
}
}
val columnRange = columns[column] ?: return null
val doubleValue = dataModel.getValueAt(row, column).toString().toDoubleOrNull() ?: return null
return if (perColumn) getColor(doubleValue, columnRange.min, columnRange.max)
else getColor(doubleValue, globalMin, globalMax)
}
override fun getRowHeaderBackground(row: ModelIndex<GridRow>, grid: DataGrid, color: Color?): Color? = null
override fun getColumnHeaderBackground(column: ModelIndex<GridColumn>, grid: DataGrid, color: Color?): Color? = null
override fun getPriority(): Int = 0
companion object {
@Suppress("UseJBColor")
val simpleGradientLightOld: MultipleGradient by lazy {
MultipleGradient(floatArrayOf(0f, 1f), arrayOf(Color(93, 143, 244),
Color(212, 226, 255)))
}
@Suppress("UseJBColor")
val simpleGradientLight: MultipleGradient by lazy {
MultipleGradient(floatArrayOf(0f, 1f), arrayOf(Color(54, 150, 80),
Color(242, 252, 243)))
}
fun getSimpleGradientLight(useOldColors: Boolean): MultipleGradient = if (useOldColors) simpleGradientLightOld else simpleGradientLight
@Suppress("UseJBColor")
val simpleGradientDarkOld: MultipleGradient by lazy {
MultipleGradient(floatArrayOf(0f, 1f), arrayOf(Color(54, 106, 207),
Color(37, 50, 77)))
}
@Suppress("UseJBColor")
val simpleGradientDark: MultipleGradient by lazy {
MultipleGradient(floatArrayOf(0f, 1f), arrayOf(Color(87, 150, 92),
Color(37, 54, 39)))
}
fun getSimpleGradientDark(useOldColors: Boolean): MultipleGradient = if (useOldColors) simpleGradientDarkOld else simpleGradientDark
// Test 3-colors gradient for diverging coloring.
@Suppress("UseJBColor")
val multipleGradientLightOld: MultipleGradient by lazy {
MultipleGradient(floatArrayOf(0f, 0.5f, 1f), arrayOf(Color(88, 140, 243),
Color.WHITE,
Color(228, 108, 120)))
}
@Suppress("UseJBColor")
val multipleGradientLight: MultipleGradient by lazy {
MultipleGradient(floatArrayOf(0f, 0.5f, 1f), arrayOf(Color(54, 150, 80),
Color.WHITE,
Color(228, 108, 120)))
}
fun getMultipleGradientLight(useOldColors: Boolean): MultipleGradient = if (useOldColors) multipleGradientLightOld else multipleGradientLight
@Suppress("UseJBColor")
val multipleGradientDarkOld: MultipleGradient by lazy {
MultipleGradient(floatArrayOf(0f, 0.5f, 1f), arrayOf(Color(54, 106, 207, ),
Color(30, 31, 34),
Color(189, 87, 87)))
}
@Suppress("UseJBColor")
val multipleGradientDark: MultipleGradient by lazy {
MultipleGradient(floatArrayOf(0f, 0.5f, 1f), arrayOf(Color(87, 150, 92),
Color(30, 31, 34),
Color(189, 87, 87)))
}
fun getMultipleGradientDark(useOldColors: Boolean): MultipleGradient = if (useOldColors) multipleGradientDarkOld else multipleGradientDark
val HEATMAP_OLD_COLORS : Key<Boolean> = Key.create<Boolean>("HEATMAP_OLD_COLORS")
private const val COLOR_BOOLEAN_COLUMNS = "table.view.heatmap.color.boolean.columns"
private const val PER_COLUMN_COLORING = "table.view.heatmap.color.per.columns"
private const val COLORING_MODE = "table.view.heatmap.coloring.mode"
fun getColoringMode(): ColoringMode = ColoringMode.getByName(PropertiesComponent.getInstance().getValue(COLORING_MODE))
fun setColoringMode(mode: ColoringMode): Unit = PropertiesComponent.getInstance().setValue(COLORING_MODE, mode.name)
fun isPerColumnColoringEnabled(): Boolean = PropertiesComponent.getInstance().getBoolean(PER_COLUMN_COLORING, false)
fun setPerColumnColoringEnabled(value: Boolean): Unit = PropertiesComponent.getInstance().setValue(PER_COLUMN_COLORING, value)
fun isColorBooleanColumnsEnabled(): Boolean = PropertiesComponent.getInstance().getBoolean(COLOR_BOOLEAN_COLUMNS, true)
fun setColorBooleanColumnsEnabled(value: Boolean): Unit = PropertiesComponent.getInstance().setValue(COLOR_BOOLEAN_COLUMNS, value, true)
fun installOn(dataGrid: DataGrid): TableHeatmapColorLayer? {
val gridColorModel = dataGrid.colorModel as? GridColorModelImpl ?: return null
val tableResultView = dataGrid.resultView as? TableResultView ?: return null
val useOldColors = dataGrid.getUserData(HEATMAP_OLD_COLORS) == true
val tableHeatmapColorLayer = TableHeatmapColorLayer(dataGrid, tableResultView, useOldColors)
Disposer.register(dataGrid, tableHeatmapColorLayer)
gridColorModel.addLayer(tableHeatmapColorLayer)
tableResultView.repaint()
tableResultView.showHorizontalLines = true
return tableHeatmapColorLayer
}
}
}

View File

@@ -2,8 +2,10 @@ package com.intellij.database.datagrid
import com.intellij.database.DatabaseDataKeys
import com.intellij.ide.DataManager
import com.intellij.ide.util.PropertiesComponent
import com.intellij.openapi.actionSystem.PlatformCoreDataKeys
import com.intellij.openapi.fileEditor.FileEditor
import com.intellij.openapi.project.Project
import com.intellij.util.containers.TreeTraversal
import com.intellij.util.ui.UIUtil
import java.awt.Component
@@ -65,3 +67,10 @@ private fun preferredRowHeight(table: JTable, row: Int): Int {
}
return height
}
const val COLORED_BY_DEFAULT: String = "datagrid.heatmap.switchedByDefault"
fun setHeatmapColoringEnable(project: Project, value: Boolean) {
PropertiesComponent.getInstance(project).setValue(COLORED_BY_DEFAULT, value, true)
}

View File

@@ -0,0 +1,38 @@
package com.intellij.database.run.actions
import com.intellij.database.datagrid.GridUtil
import com.intellij.database.datagrid.color.GridColorModelImpl
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.project.DumbAwareToggleAction
import com.intellij.database.datagrid.color.TableHeatmapColorLayer
abstract class ToggleTableViewBaseAction : DumbAwareToggleAction() {
override fun update(e: AnActionEvent) {
val dataGrid = GridUtil.getDataGrid(e.dataContext)
e.presentation.isEnabled = dataGrid != null
if (e.presentation.isEnabled) {
super.update(e)
}
}
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
protected fun getOrCreateHeatMapColorLayer(e: AnActionEvent) : TableHeatmapColorLayer? {
val heatmapColorLayer = getHeatMapColorLayer(e)
if (heatmapColorLayer != null)
return heatmapColorLayer
val grid = GridUtil.getDataGrid(e.dataContext) ?: return null
return TableHeatmapColorLayer.installOn(grid)
}
protected fun getHeatMapColorLayer(e: AnActionEvent): TableHeatmapColorLayer? {
return getGridColorModel(e)?.getLayer(TableHeatmapColorLayer::class.java) as? TableHeatmapColorLayer
}
private fun getGridColorModel(e: AnActionEvent): GridColorModelImpl? {
val grid = GridUtil.getDataGrid(e.dataContext) ?: return null
return grid.colorModel as? GridColorModelImpl
}
}

View File

@@ -0,0 +1,27 @@
package com.intellij.database.run.actions
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.database.datagrid.color.TableHeatmapColorLayer
class ToggleTableViewColorBooleanColumnsAction : ToggleTableViewBaseAction() {
override fun update(e: AnActionEvent) {
super.update(e)
if (e.presentation.isEnabled) {
e.presentation.isEnabled = getHeatMapColorLayer(e) != null
}
}
override fun isSelected(e: AnActionEvent): Boolean {
val heatmapLayer = getHeatMapColorLayer(e) ?: return false
return heatmapLayer.colorBooleanColumns
}
override fun setSelected(e: AnActionEvent, state: Boolean) {
val heatmapLayer = getHeatMapColorLayer(e) ?: return
heatmapLayer.colorBooleanColumns = state
// Persisting to restore on next table creation.
TableHeatmapColorLayer.setColorBooleanColumnsEnabled(state)
}
}

View File

@@ -0,0 +1,26 @@
package com.intellij.database.run.actions
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.database.datagrid.color.TableHeatmapColorLayer
class ToggleTableViewColorPerColumnAction : ToggleTableViewBaseAction() {
override fun update(e: AnActionEvent) {
super.update(e)
if (e.presentation.isEnabled) {
e.presentation.isEnabled = getHeatMapColorLayer(e) != null
}
}
override fun isSelected(e: AnActionEvent): Boolean {
val heatmapLayer = getHeatMapColorLayer(e) ?: return false
return heatmapLayer.perColumn
}
override fun setSelected(e: AnActionEvent, state: Boolean) {
val heatmapLayer = getHeatMapColorLayer(e) ?: return
heatmapLayer.perColumn = state
TableHeatmapColorLayer.setPerColumnColoringEnabled(heatmapLayer.perColumn)
}
}

View File

@@ -0,0 +1,26 @@
package com.intellij.database.run.actions
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.database.datagrid.color.TableHeatmapColorLayer
class ToggleTableViewColorPerTableAction : ToggleTableViewBaseAction() {
override fun update(e: AnActionEvent) {
super.update(e)
if (e.presentation.isEnabled) {
e.presentation.isEnabled = getHeatMapColorLayer(e) != null
}
}
override fun isSelected(e: AnActionEvent): Boolean {
val heatmapLayer = getHeatMapColorLayer(e) ?: return false
return !heatmapLayer.perColumn
}
override fun setSelected(e: AnActionEvent, state: Boolean) {
val heatmapLayer = getHeatMapColorLayer(e) ?: return
heatmapLayer.perColumn = !state
TableHeatmapColorLayer.setPerColumnColoringEnabled(heatmapLayer.perColumn)
}
}

View File

@@ -0,0 +1,19 @@
package com.intellij.database.run.actions
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.database.datagrid.color.TableHeatmapColorLayer
import com.intellij.database.datagrid.setHeatmapColoringEnable
class ToggleTableViewColoringModeDivergingAction : ToggleTableViewBaseAction() {
override fun isSelected(e: AnActionEvent): Boolean {
return getHeatMapColorLayer(e)?.coloringMode == TableHeatmapColorLayer.ColoringMode.DIVERGING
}
override fun setSelected(e: AnActionEvent, state: Boolean) {
if (state) {
getOrCreateHeatMapColorLayer(e)?.coloringMode = TableHeatmapColorLayer.ColoringMode.DIVERGING
TableHeatmapColorLayer.setColoringMode(TableHeatmapColorLayer.ColoringMode.DIVERGING)
e.project?.let { setHeatmapColoringEnable(it, true) }
}
}
}

View File

@@ -0,0 +1,21 @@
package com.intellij.database.run.actions
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.database.datagrid.color.TableHeatmapColorLayer
import com.intellij.database.datagrid.setHeatmapColoringEnable
/** Enables or disables heatmap-styled coloring of table cells. */
class ToggleTableViewColoringModeOffAction : ToggleTableViewBaseAction() {
override fun isSelected(e: AnActionEvent): Boolean {
val heatmapLayer = getHeatMapColorLayer(e) ?: return true
return heatmapLayer.coloringMode == TableHeatmapColorLayer.ColoringMode.OFF
}
override fun setSelected(e: AnActionEvent, state: Boolean) {
if (state) {
getHeatMapColorLayer(e)?.coloringMode = TableHeatmapColorLayer.ColoringMode.OFF
TableHeatmapColorLayer.setColoringMode(TableHeatmapColorLayer.ColoringMode.OFF)
e.project?.let { setHeatmapColoringEnable(it, false) }
}
}
}

View File

@@ -0,0 +1,19 @@
package com.intellij.database.run.actions
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.database.datagrid.color.TableHeatmapColorLayer
import com.intellij.database.datagrid.setHeatmapColoringEnable
class ToggleTableViewColoringModeSequentialAction : ToggleTableViewBaseAction() {
override fun isSelected(e: AnActionEvent): Boolean {
return getHeatMapColorLayer(e)?.coloringMode == TableHeatmapColorLayer.ColoringMode.SEQUENTIAL
}
override fun setSelected(e: AnActionEvent, state: Boolean) {
if (state) {
getOrCreateHeatMapColorLayer(e)?.coloringMode = TableHeatmapColorLayer.ColoringMode.SEQUENTIAL
TableHeatmapColorLayer.setColoringMode(TableHeatmapColorLayer.ColoringMode.SEQUENTIAL)
e.project?.let { setHeatmapColoringEnable(it, true) }
}
}
}

View File

@@ -232,7 +232,7 @@ class PyDataView(private val project: Project) : DumbAware {
companion object {
private const val DATA_VIEWER_ID = "SciView"
const val COLORED_BY_DEFAULT: String = "python.debugger.dataView.coloredByDefault"
const val COLORED_BY_DEFAULT: String = "datagrid.heatmap.switchedByDefault"
const val AUTO_RESIZE: String = "python.debugger.dataView.autoresize"
private const val HELP_ID = "reference.toolWindows.PyDataView"