diff --git a/docs/examples/jupyter-notebooks/f-4.8.1/theme_facet_strip_xy.ipynb b/docs/examples/jupyter-notebooks/f-4.8.1/theme_facet_strip_xy.ipynb
new file mode 100644
index 000000000..0794c0c5d
--- /dev/null
+++ b/docs/examples/jupyter-notebooks/f-4.8.1/theme_facet_strip_xy.ipynb
@@ -0,0 +1,730 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "d9ff8a46-2be6-420c-bfff-df77a7b47587",
+ "metadata": {},
+ "source": [
+ "# Horizontal and Vertical Facet Labels\n",
+ "New `theme()` parameters allow to set the style for horizontal and vertical facet labels separately:\n",
+ "\n",
+ "- `stripBackgroundX` and `stripBackgroundY` parameters set the background of horizontal and vertical facet labels respectively, specified with `elementRect()`;\n",
+ "\n",
+ "- `stripTextX` and `stripTextY` - horizontal and vertical facet labels, specified with `elementText()`."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "2aef6e9b-8f16-4134-a395-d7fa8ea7f3bb",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ " "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ " "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "%useLatestDescriptors\n",
+ "%use lets-plot\n",
+ "\n",
+ "%use dataframe"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "fad33652-bcfd-41c4-8fe2-670d1651e5ca",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Lets-Plot Kotlin API v.0.0.0-SNAPSHOT. Frontend: Notebook with dynamically loaded JS. Lets-Plot JS v.4.5.0."
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "LetsPlot.getInfo()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "a8ecf448-aebe-480d-ae4d-b8f39aed0a5b",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "val df = dataFrameOf(\"animal_type\", \"animal\", \"weight\", \"diet\")(\n",
+ " \"pet\", \"cat\", 5, \"carnivore\",\n",
+ " \"pet\", \"dog\", 10, \"carnivore\",\n",
+ " \"pet\", \"rabbit\", 2, \"herbivore\",\n",
+ " \"pet\", \"hamster\", 1, \"herbivore\",\n",
+ "\n",
+ " \"farm\", \"cow\", 500, \"herbivore\",\n",
+ " \"farm\", \"pig\", 100, \"carnivore\",\n",
+ " \"farm\", \"horse\", 700, \"herbivore\",\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "7ffdc8df-85dc-4c7b-bdb9-c5734e7f22cc",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "val p = letsPlot(df.toMap()) { x = \"animal\"; y = \"weight\" } +\n",
+ " geomBar(stat = Stat.identity) +\n",
+ " facetGrid(x = \"animal_type\", y = \"diet\", scales = \"free\") +\n",
+ " themeBW()\n",
+ "\n",
+ "p"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c4b03b06-6ddb-45b3-ad4e-8c8cbaad5a4c",
+ "metadata": {},
+ "source": [
+ "Change the style for facet labels:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "3d27e4d9-f648-4c03-85dc-33979bc4eeb2",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "p + theme(stripTextX = elementText(face = \"bold\"),\n",
+ " stripBackgroundX = elementRect(fill = \"pink\"),\n",
+ " stripTextY = elementText(face = \"italic\"),\n",
+ " stripBackgroundY = elementRect(fill = \"light_blue\"))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "957baf07-7e3b-4dbb-93c6-3e7858c48e36",
+ "metadata": {},
+ "source": [
+ "Hide horizontal facet labels:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "57bf5c50-7728-4805-91fb-7dcfd6380b2c",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "p + theme(stripTextX = elementBlank())"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Kotlin",
+ "language": "kotlin",
+ "name": "kotlin"
+ },
+ "language_info": {
+ "codemirror_mode": "text/x-kotlin",
+ "file_extension": ".kt",
+ "mimetype": "text/x-kotlin",
+ "name": "kotlin",
+ "nbconvert_exporter": "",
+ "pygments_lexer": "kotlin",
+ "version": "1.9.23"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/docs/examples/jupyter-notebooks/f-4.8.1/theme_legend_key.ipynb b/docs/examples/jupyter-notebooks/f-4.8.1/theme_legend_key.ipynb
new file mode 100644
index 000000000..d7967dba8
--- /dev/null
+++ b/docs/examples/jupyter-notebooks/f-4.8.1/theme_legend_key.ipynb
@@ -0,0 +1,1418 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "5ccaa519-641c-4c68-a50a-668e17b9fe2d",
+ "metadata": {},
+ "source": [
+ "# Legend Key Parameters in `theme()`\n",
+ "New parameters in `theme()` to customize the legend key:\n",
+ "\n",
+ "- `legendKey` - background underneath legend keys, set with `elementRect()`\n",
+ "- `legendKeySize` - size of legend keys\n",
+ "- `legendKeyWidth` - key background width\n",
+ "- `legendKeyHeight` - key background height\n",
+ "- `legendKeySpacing` - spacing between legend keys\n",
+ "- `legendKeySpacingX` - spacing in the horizontal direction\n",
+ "- `legendKeySpacingY` - spacing in the vertical direction"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "503686e9-e057-4afe-a003-475fe00d4c07",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ " "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "%useLatestDescriptors\n",
+ "%use lets-plot\n",
+ "\n",
+ "%use dataframe"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "c4138f8c-c0d6-49d7-ba48-b30a55d5df68",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Lets-Plot Kotlin API v.0.0.0-SNAPSHOT. Frontend: Notebook with dynamically loaded JS. Lets-Plot JS v.4.5.0."
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "LetsPlot.getInfo()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "b6b8988b-e5ba-4fda-a322-ad1d215e45c5",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/kotlindataframe+json": "{\"nrow\":3,\"ncol\":12,\"columns\":[\"untitled\",\"manufacturer\",\"model\",\"displ\",\"year\",\"cyl\",\"trans\",\"drv\",\"cty\",\"hwy\",\"fl\",\"class\"],\"kotlin_dataframe\":[{\"untitled\":1,\"manufacturer\":\"audi\",\"model\":\"a4\",\"displ\":1.8,\"year\":1999,\"cyl\":4,\"trans\":\"auto(l5)\",\"drv\":\"f\",\"cty\":18,\"hwy\":29,\"fl\":\"p\",\"class\":\"compact\"},{\"untitled\":2,\"manufacturer\":\"audi\",\"model\":\"a4\",\"displ\":1.8,\"year\":1999,\"cyl\":4,\"trans\":\"manual(m5)\",\"drv\":\"f\",\"cty\":21,\"hwy\":29,\"fl\":\"p\",\"class\":\"compact\"},{\"untitled\":3,\"manufacturer\":\"audi\",\"model\":\"a4\",\"displ\":2.0,\"year\":2008,\"cyl\":4,\"trans\":\"manual(m6)\",\"drv\":\"f\",\"cty\":20,\"hwy\":31,\"fl\":\"p\",\"class\":\"compact\"}]}",
+ "text/html": [
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "\n",
+ "DataFrame: rowsCount = 3, columnsCount = 12
\n",
+ "untitled | manufacturer | model | displ | year | cyl | trans | drv | cty | hwy | fl | class |
---|
1 | audi | a4 | 1.800000 | 1999 | 4 | auto(l5) | f | 18 | 29 | p | compact |
2 | audi | a4 | 1.800000 | 1999 | 4 | manual(m5) | f | 21 | 29 | p | compact |
3 | audi | a4 | 2.000000 | 2008 | 4 | manual(m6) | f | 20 | 31 | p | compact |
\n",
+ " \n",
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "val mpg = DataFrame.readCSV(\"https://raw.githubusercontent.com/JetBrains/lets-plot-docs/master/data/mpg.csv\")\n",
+ "mpg.head(3)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "9b416d09-e400-4142-a929-dc07b8f6aeca",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "val p = letsPlot(mpg.toMap()) { x = \"hwy\" } +\n",
+ " geomDotplot(color=\"pen\") { fill = \"class\" } +\n",
+ " theme(legendBackground = elementRect(size = 0.5))\n",
+ "p"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f94f5e35-93c0-4265-93ef-49829452e64d",
+ "metadata": {},
+ "source": [
+ "Add background underneath legend keys:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "0d26cb7e-7793-4bdb-8d45-914f1fb7b202",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "val p1 = p + theme(legendKey = elementRect(fill = \"#efedf5\", color = \"#756bb1\"))\n",
+ "p1"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "405916ac-1406-4e76-aab0-1d04d34d5b65",
+ "metadata": {},
+ "source": [
+ "Change size of legend keys:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "10036c57-9cb6-4a35-9e8f-525c3ed497c5",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "p1 + theme(legendKeySize = 30)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "3f115b4e-47a3-4fdb-b300-0519870c2ef7",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "val p2 = p1 + theme(legendKeyWidth = 80, legendKeyHeight = 20)\n",
+ "p2"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1c74e052-c448-4f13-8271-6ebcd91d746c",
+ "metadata": {},
+ "source": [
+ "Add spacing between legend keys:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "8c54e347-88fc-48a0-a75b-230b9a952fc1",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "p2 + theme(legendKeySpacingY = 10)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Kotlin",
+ "language": "kotlin",
+ "name": "kotlin"
+ },
+ "language_info": {
+ "codemirror_mode": "text/x-kotlin",
+ "file_extension": ".kt",
+ "mimetype": "text/x-kotlin",
+ "name": "kotlin",
+ "nbconvert_exporter": "",
+ "pygments_lexer": "kotlin",
+ "version": "1.9.23"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/docs/examples/jupyter-notebooks/f-4.8.1/theme_legend_margins.ipynb b/docs/examples/jupyter-notebooks/f-4.8.1/theme_legend_margins.ipynb
new file mode 100644
index 000000000..37c9eb749
--- /dev/null
+++ b/docs/examples/jupyter-notebooks/f-4.8.1/theme_legend_margins.ipynb
@@ -0,0 +1,1605 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "6dba04d1-a2dd-44a3-8615-5f77e9b26d20",
+ "metadata": {},
+ "source": [
+ "# Legend Spacing and Margins\n",
+ "New parameters in theme() to customize the legend spacing and margins:\n",
+ "\n",
+ "\n",
+ "- `legendBoxSpacing` - spacing between plotting area and legend box;\n",
+ "\n",
+ "- `legendMargin` - margin around each legend;\n",
+ "\n",
+ "- `legendSpacing` - spacing between legends, `legendSpacingX/legendSpacingY` - in the horizontal/vertical direction.\n",
+ "\n",
+ "Arrangement of multiple legends:\n",
+ "- `fun legendBoxHorizontal()`\n",
+ "- `fun legendBoxVertical()`\n",
+ "\n",
+ "Justification of each legend within the overall bounding box:\n",
+ "\n",
+ "- `fun legendBoxJustificationLeft()`\n",
+ "- `fun legendBoxJustificationRight()`\n",
+ "- `fun legendBoxJustificationTop()`\n",
+ "- `fun legendBoxJustificationBottom()`\n",
+ "- `fun legendBoxJustificationCenter()`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "7b1c280b-8d5c-4829-840e-9e51d7418348",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ " "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "%useLatestDescriptors\n",
+ "%use lets-plot\n",
+ "\n",
+ "%use dataframe"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "ff612f73-1d06-4008-9fe3-200f70a42bf1",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "Lets-Plot Kotlin API v.0.0.0-SNAPSHOT. Frontend: Notebook with dynamically loaded JS. Lets-Plot JS v.4.5.0."
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "LetsPlot.getInfo()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "31c54759-634a-45c2-8616-c9aa655433ce",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/kotlindataframe+json": "{\"nrow\":3,\"ncol\":12,\"columns\":[\"untitled\",\"manufacturer\",\"model\",\"displ\",\"year\",\"cyl\",\"trans\",\"drv\",\"cty\",\"hwy\",\"fl\",\"class\"],\"kotlin_dataframe\":[{\"untitled\":1,\"manufacturer\":\"audi\",\"model\":\"a4\",\"displ\":1.8,\"year\":1999,\"cyl\":4,\"trans\":\"auto(l5)\",\"drv\":\"f\",\"cty\":18,\"hwy\":29,\"fl\":\"p\",\"class\":\"compact\"},{\"untitled\":2,\"manufacturer\":\"audi\",\"model\":\"a4\",\"displ\":1.8,\"year\":1999,\"cyl\":4,\"trans\":\"manual(m5)\",\"drv\":\"f\",\"cty\":21,\"hwy\":29,\"fl\":\"p\",\"class\":\"compact\"},{\"untitled\":3,\"manufacturer\":\"audi\",\"model\":\"a4\",\"displ\":2.0,\"year\":2008,\"cyl\":4,\"trans\":\"manual(m6)\",\"drv\":\"f\",\"cty\":20,\"hwy\":31,\"fl\":\"p\",\"class\":\"compact\"}]}",
+ "text/html": [
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ "\n",
+ "DataFrame: rowsCount = 3, columnsCount = 12
\n",
+ "untitled | manufacturer | model | displ | year | cyl | trans | drv | cty | hwy | fl | class |
---|
1 | audi | a4 | 1.800000 | 1999 | 4 | auto(l5) | f | 18 | 29 | p | compact |
2 | audi | a4 | 1.800000 | 1999 | 4 | manual(m5) | f | 21 | 29 | p | compact |
3 | audi | a4 | 2.000000 | 2008 | 4 | manual(m6) | f | 20 | 31 | p | compact |
\n",
+ " \n",
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "val mpg = DataFrame.readCSV(\"https://raw.githubusercontent.com/JetBrains/lets-plot-docs/master/data/mpg.csv\")\n",
+ "mpg.head(3)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "baceae21-9cb1-4eec-9248-d891f2a7e2c6",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "val p = letsPlot(mpg.toMap()) { x = \"displ\"; y = \"cty\" } +\n",
+ " geomPoint(shape = 21) { fill = \"drv\"; size = \"hwy\" } +\n",
+ " scaleSize(range = 1 to 10, breaks = listOf(15, 30, 40)) +\n",
+ " theme(legendBackground = elementRect(size = 1)).legendPositionBottom()\n",
+ "\n",
+ "p"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "2296f1cc-9d6a-443a-9565-b62364a202e1",
+ "metadata": {},
+ "source": [
+ "#### `legendMargin`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "57e085ba-b05a-4775-81d2-488a7b8021f7",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "p + theme(legendMargin = listOf(10, 20))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "1d657039",
+ "metadata": {},
+ "source": [
+ "#### Arrangement in Legend Box"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "ad6f7ad3",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "p + theme().legendBoxHorizontal()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f8794528",
+ "metadata": {},
+ "source": [
+ "#### Legend Justification within Overall Bounding Box"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "1994ada1",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "p + theme().legendBoxJustificationCenter()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "d973239e",
+ "metadata": {},
+ "source": [
+ "#### `legendBoxSpacing`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "471c192f",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "p + theme(legendBoxSpacing = 50).legendBoxHorizontal()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "e3cc151b-963e-4264-a24a-444311bbc7c2",
+ "metadata": {},
+ "source": [
+ "#### `legendSpacing`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "313bb630-b97d-4015-9caf-8e9b5d9de318",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ " \n",
+ " "
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "p + theme(legendSpacing = 50).legendBoxHorizontal()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Kotlin",
+ "language": "kotlin",
+ "name": "kotlin"
+ },
+ "language_info": {
+ "codemirror_mode": "text/x-kotlin",
+ "file_extension": ".kt",
+ "mimetype": "text/x-kotlin",
+ "name": "kotlin",
+ "nbconvert_exporter": "",
+ "pygments_lexer": "kotlin",
+ "version": "1.9.23"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/plot-api/src/commonMain/kotlin/org/jetbrains/letsPlot/themes/theme.kt b/plot-api/src/commonMain/kotlin/org/jetbrains/letsPlot/themes/theme.kt
index abc42d507..832991d94 100644
--- a/plot-api/src/commonMain/kotlin/org/jetbrains/letsPlot/themes/theme.kt
+++ b/plot-api/src/commonMain/kotlin/org/jetbrains/letsPlot/themes/theme.kt
@@ -73,7 +73,26 @@ import org.jetbrains.letsPlot.intern.filterNonNullValues
* @param legendBackground Background of legend.
* @param legendText Legend item labels.
* @param legendTitle Title of legend.
- *
+ * @param legendMargin Margin around each legend.
+ * Margins around the text.
+ * The margin may be specified using a number or a list of numbers:
+ * - a number or list of one number - the same margin it applied to all four sides;
+ * - a list of two numbers - the first margin applies to the top and bottom, the second - to the left and right;
+ * - a list of three numbers - the first margin applies to the top, the second - to the right and left,
+ * the third - to the bottom;
+ * - a list of four numbers - the margins are applied to the top, right, bottom and left in that order.
+ * It is acceptable to use `null` for any side; in this case, the default side value for the legend margin side will be used.
+ * @param legendSpacing Spacing between legends.
+ * @param legendSpacingX Spacing between legends in the horizontal direction.
+ * @param legendSpacingY Spacing between legends in the horizontal direction.
+ * @param legendKey Background underneath legend keys.
+ * @param legendKeySize Size of legend keys.
+ * @param legendKeyWidth Key background width.
+ * @param legendKeyHeight Key background height.
+ * @param legendKeySpacing Spacing between legend keys
+ * @param legendKeySpacingX Spacing between legend keys in the horizontal direction.
+ * @param legendKeySpacingY Spacing between legend keys in the horizontal direction.
+ * @param legendBoxSpacing Spacing between plotting area and legend box.
* @param panelBackground Background of plotting area.
* @param panelBorder Border around plotting area.
* @param panelBorderOntop Option to place border around plotting area over the data layers.
@@ -134,7 +153,11 @@ import org.jetbrains.letsPlot.intern.filterNonNullValues
* A value of "panel" means that caption is aligned to the plot panels.
* A value of "plot" means that caption is aligned to the entire plot (excluding margins).
* @param stripBackground Background of facet labels.
+ * @param stripBackgroundX Horizontal facet background.
+ * @param stripBackgroundY Vertical facet background.
* @param stripText Facet labels.
+ * @param stripTextX Horizontal facet labels.
+ * @param stripTextY Vertical facet labels.
*
* @param axisTooltip Axes tooltips.
* @param axisTooltipX Axes tooltips.
@@ -195,6 +218,20 @@ class theme(
legendBackground: Any? = null,
legendText: Any? = null,
legendTitle: Any? = null,
+ legendMargin: Any? = null,
+ legendSpacing: Number? = null,
+ legendSpacingX: Number? = null,
+ legendSpacingY: Number? = null,
+
+ legendKey: Any? = null,
+ legendKeySize: Number? = null,
+ legendKeyWidth: Number? = null,
+ legendKeyHeight: Number? = null,
+ legendKeySpacing: Number? = null,
+ legendKeySpacingX: Number? = null,
+ legendKeySpacingY: Number? = null,
+
+ legendBoxSpacing: Number? = null,
panelBackground: Any? = null,
panelBorder: Any? = null,
@@ -230,7 +267,11 @@ class theme(
plotCaptionPosition: Any? = null,
stripBackground: Any? = null,
+ stripBackgroundX: Any? = null,
+ stripBackgroundY: Any? = null,
stripText: Any? = null,
+ stripTextX: Any? = null,
+ stripTextY: Any? = null,
axisTooltip: Any? = null,
axisTooltipX: Any? = null,
@@ -285,6 +326,20 @@ class theme(
Option.Theme.LEGEND_BKGR_RECT to legendBackground,
Option.Theme.LEGEND_TEXT to legendText,
Option.Theme.LEGEND_TITLE to legendTitle,
+ Option.Theme.LEGEND_MARGIN to legendMargin,
+ Option.Theme.LEGEND_SPACING to legendSpacing,
+ Option.Theme.LEGEND_SPACING_X to legendSpacingX,
+ Option.Theme.LEGEND_SPACING_Y to legendSpacingY,
+
+ Option.Theme.LEGEND_KEY_RECT to legendKey,
+ Option.Theme.LEGEND_KEY_SIZE to legendKeySize,
+ Option.Theme.LEGEND_KEY_WIDTH to legendKeyWidth,
+ Option.Theme.LEGEND_KEY_HEIGHT to legendKeyHeight,
+ Option.Theme.LEGEND_KEY_SPACING to legendKeySpacing,
+ Option.Theme.LEGEND_KEY_SPACING_X to legendKeySpacingX,
+ Option.Theme.LEGEND_KEY_SPACING_Y to legendKeySpacingY,
+
+ Option.Theme.LEGEND_BOX_SPACING to legendBoxSpacing,
Option.Theme.PANEL_BKGR_RECT to panelBackground,
Option.Theme.PANEL_BORDER_RECT to panelBorder,
@@ -316,7 +371,11 @@ class theme(
Option.Theme.PLOT_CAPTION_POSITION to plotCaptionPosition,
Option.Theme.FACET_STRIP_BGR_RECT to stripBackground,
+ Option.Theme.FACET_STRIP_BGR_RECT_X to stripBackgroundX,
+ Option.Theme.FACET_STRIP_BGR_RECT_Y to stripBackgroundY,
Option.Theme.FACET_STRIP_TEXT to stripText,
+ Option.Theme.FACET_STRIP_TEXT_X to stripTextX,
+ Option.Theme.FACET_STRIP_TEXT_Y to stripTextY,
Option.Theme.AXIS_TOOLTIP to axisTooltip,
Option.Theme.AXIS_TOOLTIP_X to axisTooltipX,
@@ -348,11 +407,11 @@ class theme(
return newTheme
}
- fun legendPositionNone() = withOption(Option.Theme.LEGEND_POSITION, VAL_LEGEND_POS_NONE)
- fun legendPositionLeft() = withOption(Option.Theme.LEGEND_POSITION, VAL_LEGEND_POS_LEFT)
- fun legendPositionRight() = withOption(Option.Theme.LEGEND_POSITION, VAL_LEGEND_POS_RIGHT)
- fun legendPositionBottom() = withOption(Option.Theme.LEGEND_POSITION, VAL_LEGEND_POS_BOTTOM)
- fun legendPositionTop() = withOption(Option.Theme.LEGEND_POSITION, VAL_LEGEND_POS_TOP)
+ fun legendPositionNone() = withOption(Option.Theme.LEGEND_POSITION, Option.Theme.Legend.POSITION_NONE)
+ fun legendPositionLeft() = withOption(Option.Theme.LEGEND_POSITION, Option.Theme.Legend.POSITION_LEFT)
+ fun legendPositionRight() = withOption(Option.Theme.LEGEND_POSITION, Option.Theme.Legend.POSITION_RIGHT)
+ fun legendPositionBottom() = withOption(Option.Theme.LEGEND_POSITION, Option.Theme.Legend.POSITION_BOTTOM)
+ fun legendPositionTop() = withOption(Option.Theme.LEGEND_POSITION, Option.Theme.Legend.POSITION_TOP)
/**
* Specifies the legend position relative to the plot drawing area.
@@ -367,7 +426,7 @@ class theme(
)
}
- fun legendJustificationCenter() = withOption(Option.Theme.LEGEND_JUSTIFICATION, VAL_LEGEND_JUSTIFICATION_CENTER)
+ fun legendJustificationCenter() = withOption(Option.Theme.LEGEND_JUSTIFICATION, Option.Theme.Legend.JUSTIFICATION_CENTER)
/**
* Specifies the anchor point for positioning legend inside plot.
@@ -381,20 +440,23 @@ class theme(
)
}
- fun legendDirectionHorizontal() = withOption(Option.Theme.LEGEND_DIRECTION, VAL_LEGEND_DIRECTION_HORIZONTAL)
- fun legendDirectionVertical() = withOption(Option.Theme.LEGEND_DIRECTION, VAL_LEGEND_DIRECTION_VERTICAL)
-
- private companion object {
- private const val VAL_ELEMENT_BLANK = "blank"
- private const val VAL_LEGEND_POS_NONE = "none"
- private const val VAL_LEGEND_POS_LEFT = "left"
- private const val VAL_LEGEND_POS_RIGHT = "right"
- private const val VAL_LEGEND_POS_BOTTOM = "bottom"
- private const val VAL_LEGEND_POS_TOP = "top"
- private const val VAL_LEGEND_JUSTIFICATION_CENTER = "center"
- private const val VAL_LEGEND_DIRECTION_HORIZONTAL = "horizontal"
- private const val VAL_LEGEND_DIRECTION_VERTICAL = "vertical"
- }
+ fun legendDirectionHorizontal() = withOption(Option.Theme.LEGEND_DIRECTION, Option.Theme.Legend.DIRECTION_HORIZONTAL)
+ fun legendDirectionVertical() = withOption(Option.Theme.LEGEND_DIRECTION, Option.Theme.Legend.DIRECTION_VERTICAL)
+
+ /**
+ * Arrangement of multiple legends: horizontal or vertical.
+ */
+ fun legendBoxHorizontal() = withOption(Option.Theme.LEGEND_BOX, Option.Theme.Legend.ARRANGEMENT_HORIZONTAL)
+ fun legendBoxVertical() = withOption(Option.Theme.LEGEND_BOX, Option.Theme.Legend.ARRANGEMENT_VERTICAL)
+
+ /**
+ * Justification of each legend within the overall bounding box, when there are multiple legends.
+ */
+ fun legendBoxJustificationLeft() = withOption(Option.Theme.LEGEND_BOX_JUST, Option.Theme.Legend.JUSTIFICATION_LEFT)
+ fun legendBoxJustificationRight() = withOption(Option.Theme.LEGEND_BOX_JUST, Option.Theme.Legend.JUSTIFICATION_RIGHT)
+ fun legendBoxJustificationTop() = withOption(Option.Theme.LEGEND_BOX_JUST, Option.Theme.Legend.JUSTIFICATION_TOP)
+ fun legendBoxJustificationBottom() = withOption(Option.Theme.LEGEND_BOX_JUST, Option.Theme.Legend.JUSTIFICATION_BOTTOM)
+ fun legendBoxJustificationCenter() = withOption(Option.Theme.LEGEND_BOX_JUST, Option.Theme.Legend.JUSTIFICATION_CENTER)
}
/**