Skip to content

Commit

Permalink
Use list of variable names for tooltip configuration (#376)
Browse files Browse the repository at this point in the history
  • Loading branch information
OLarionova-HORIS authored May 26, 2021
1 parent 87d8031 commit fc908bd
Show file tree
Hide file tree
Showing 9 changed files with 386 additions and 95 deletions.
Binary file added docs/examples/images/tooltips_8.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/examples/images/tooltips_9.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
319 changes: 231 additions & 88 deletions docs/examples/jupyter-notebooks/tooltip_config.ipynb

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions docs/tooltips.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Tooltip Customization

- [Tooltip variable list](#variables)
- [Examples](#example-variables)

------


The following functions set lines, define formatting of the tooltip, its location and width:
```
tooltips=layer_tooltips(variables)
.format(field, format)
.line(template)
.anchor(position)
.min_width(value)
```

<a id="variables"></a>
### Tooltip variable list: `layer_tooltips(variables = ['varName1', ... , 'varNameN'] )`
The `variables` parameter defines a list of variable names, which values will be placed line by line in the general tooltip.
If formatting is specified for a variable from this list (with the `format` function), it will be applied.
Otherwise, the default formatting is used.
Additional tooltip lines can be specified using the `line` functions.


<a id="example-variables"></a>
### Examples

Set list of variables to place them in a multiline tooltip with the default formatting:

```
ggplot(mpg) + geom_point(aes(x='displ', y='cty', fill='drv', size='hwy'), shape=21, color='black',
tooltips=layer_tooltips(['manufacturer', 'model', 'class', 'drv']))
```
![](examples/images/tooltips_8.png)


Define the format for the variable from the list and specify an additional line:
```
ggplot(mpg) + geom_point(aes(x='displ', y='cty', fill='drv', size='hwy'), shape=21, color='black',
tooltips=layer_tooltips(['manufacturer', 'model', 'class', 'drv'])
.format('drv', '{}wd')
.line('cty/hwy [mpg]|@cty/@hwy'))
```

![](examples/images/tooltips_9.png)
4 changes: 4 additions & 0 deletions future_changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

### Added

- In tooltip customization API:
- `layer_tooltips(variables)` - the new parameter `variables` defines a list of variable names, which values will be placed line by line in the general tooltip.
See: [Tooltip Customization](https://github.com/JetBrains/lets-plot/blob/master/docs/tooltips.md).

### Changed

### Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ object Option {
const val SHOW_LEGEND = "show_legend"
const val TOOLTIPS = "tooltips"
const val TOOLTIP_LINES = "tooltip_lines"
const val TOOLTIP_VARIABLES = "tooltip_variables"
const val TOOLTIP_FORMATS = "tooltip_formats"
const val TOOLTIP_ANCHOR = "tooltip_anchor"
const val TOOLTIP_MIN_WIDTH = "tooltip_min_width"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,38 @@ class TooltipConfig(
} else {
null
},
tooltipFormats = getList(Option.Layer.TOOLTIP_FORMATS)
tooltipFormats = getList(Option.Layer.TOOLTIP_FORMATS),
tooltipVariables = getStringList(Option.Layer.TOOLTIP_VARIABLES)
).parse()
}

private inner class TooltipConfigParseHelper(
private val tooltipLines: List<String>?,
tooltipFormats: List<*>
tooltipFormats: List<*>,
tooltipVariables: List<String>
) {
// Key is Pair: <field name> + <isAes flag>
private val myValueSources: MutableMap<Pair<String, Boolean>, ValueSource> = prepareFormats(tooltipFormats)
.mapValues { (field, format) ->
createValueSource(fieldName = field.first, isAes = field.second, format = format)
}.toMutableMap()

// Create tooltip lines from the given variable list
private val myLinesForVariableList = tooltipVariables.map { variableName ->
val valueSource = getValueSource(VARIABLE_NAME_PREFIX + variableName)
TooltipLine.defaultLineForValueSource(valueSource)
}

internal fun parse(): TooltipSpecification {
val lines = tooltipLines?.map(::parseLine)
val allTooltipLines = when {
lines != null -> myLinesForVariableList + lines
myLinesForVariableList.isNotEmpty() -> myLinesForVariableList
else -> null
}
return TooltipSpecification(
myValueSources.map { it.value },
lines,
allTooltipLines,
TooltipSpecification.TooltipProperties(
anchor = readAnchor(),
minWidth = readMinWidth(),
Expand Down
78 changes: 77 additions & 1 deletion plot-config/src/jvmTest/kotlin/plot/config/TooltipConfigTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import jetbrains.datalore.plot.config.Option.Layer.GEOM
import jetbrains.datalore.plot.config.Option.Layer.TOOLTIPS
import jetbrains.datalore.plot.config.Option.Layer.TOOLTIP_FORMATS
import jetbrains.datalore.plot.config.Option.Layer.TOOLTIP_LINES
import jetbrains.datalore.plot.config.Option.Layer.TOOLTIP_VARIABLES
import jetbrains.datalore.plot.config.Option.Meta.KIND
import jetbrains.datalore.plot.config.Option.Plot.LAYERS
import jetbrains.datalore.plot.config.Option.PlotBase.DATA
Expand Down Expand Up @@ -44,7 +45,6 @@ class TooltipConfigTest {
Aes.SHAPE.name to "class"
)


@Test
fun defaultTooltips() {
val geomLayer = buildGeomPointLayer(data, mapping, tooltips = null)
Expand Down Expand Up @@ -517,6 +517,82 @@ class TooltipConfigTest {
)
}

@Test
fun `variables list to place in a tooltip with default formatting`() {
val tooltipConfig = mapOf(
TOOLTIP_VARIABLES to listOf(
"model name",
"class",
"displ",
"hwy",
"origin"
)
)
val geomLayer = buildGeomPointLayer(data, mapping, tooltips = tooltipConfig)
val expectedLines = listOf(
"model name: dodge",
"class: suv",
"displ: 1.6",
"hwy: 160.0",
"origin: US"

)
val lines = getGeneralTooltipStrings(geomLayer)
assertTooltipStrings(expectedLines, lines)
}

@Test
fun `variables list should use the defined formatting`() {
val tooltipConfig = mapOf(
TOOLTIP_VARIABLES to listOf(
"model name",
"class",
"displ",
"hwy",
"origin"
),
TOOLTIP_FORMATS to listOf(
mapOf(
FIELD to "hwy",
FORMAT to "{.2f} mpg"
)
)
)
val geomLayer = buildGeomPointLayer(data, mapping, tooltips = tooltipConfig)
val expectedLines = listOf(
"model name: dodge",
"class: suv",
"displ: 1.6",
"hwy: 160.00 mpg",
"origin: US"
)
val lines = getGeneralTooltipStrings(geomLayer)
assertTooltipStrings(expectedLines, lines)
}

@Test
fun `tooltip lines should be formed by variables list and line functions`() {
val tooltipConfig = mapOf(
TOOLTIP_VARIABLES to listOf(
"model name",
"class",
"displ"
),
TOOLTIP_LINES to listOf(
"@|@hwy mpg"
)
)
val geomLayer = buildGeomPointLayer(data, mapping, tooltips = tooltipConfig)
val expectedLines = listOf(
"model name: dodge",
"class: suv",
"displ: 1.6",
"hwy: 160.0 mpg"
)
val lines = getGeneralTooltipStrings(geomLayer)
assertTooltipStrings(expectedLines, lines)
}

companion object {

private fun buildGeomPointLayer(
Expand Down
14 changes: 11 additions & 3 deletions python-package/lets_plot/plot/tooltip.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Use of this source code is governed by the MIT license that can be found in the LICENSE file.

from .core import FeatureSpec
from typing import List, Dict
from typing import List

#
# Tooltips
Expand Down Expand Up @@ -68,13 +68,20 @@ class layer_tooltips(FeatureSpec):
"""

def __init__(self):
"""Initialize self."""
def __init__(self, variables: List[str] = None):
"""
Initialize self.
:param variables: List of strings
Variable names to place in the general tooltip with default formatting.
"""

self._tooltip_formats: List = []
self._tooltip_lines: List = None
self._tooltip_anchor = None
self._tooltip_min_width = None
self._tooltip_color = None
self._tooltip_variables = variables
super().__init__('tooltips', name=None)

def as_dict(self):
Expand Down Expand Up @@ -107,6 +114,7 @@ def as_dict(self):
d['tooltip_anchor'] = self._tooltip_anchor
d['tooltip_min_width'] = self._tooltip_min_width
d['tooltip_color'] = self._tooltip_color
d['tooltip_variables'] = self._tooltip_variables
return d

def format(self, field=None, format=None):
Expand Down

0 comments on commit fc908bd

Please sign in to comment.