2021-08-15 11:57:22 +02:00

644 lines
14 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "a0d6ef1e-d8cd-40dc-8928-aa984ea6e788",
"metadata": {},
"outputs": [],
"source": [
"{-# LANGUAGE OverloadedStrings #-}\n",
"import IHaskell.Display.Widgets"
]
},
{
"cell_type": "markdown",
"id": "bdf75813-33a0-4b98-a41a-35b3d88bcee9",
"metadata": {},
"source": [
"# The `Link` widgets\n",
"\n",
"Have you ever wanted to sync some attributes between two widgets? Are you tired of setting handlers like `getValue ... >>= setValue ...`? Then today's your lucky day!\n",
"\n",
"The link widget allows you to sync two attributes in two different widgets. The main difference with using a handler (appart from the convenience) is that they are synced on the *frontend*. This is faster because it doesn't have to be sent to and processed by the kernel first.\n",
"\n",
"The `Link` widget has two fields, `Source` and `Target`, of type `WidgetFieldPair`. `WidgetFieldPair` has a constructor that receives a a widget and a field. We can link two widgets creating a `Link` widget and setting its `Source` and `Target` fields.\n",
"\n",
"Let's see an example linking two sliders:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "107c6fc9-c1fd-433d-8719-fa3daea8bc51",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "bfa03a36-8319-4427-bb4e-79aebec8e97c",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "a37ece31-9918-468e-9e8c-c2451f8cdf4a",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- Creating the sliders\n",
"is1 <- mkIntSlider\n",
"is2 <- mkIntSlider\n",
"\n",
"-- Creating the link\n",
"link <- mkLink\n",
"setField link Source (WidgetFieldPair is1 IntValue)\n",
"setField link Target (WidgetFieldPair is2 IntValue)\n",
"\n",
"-- Displaying the widget\n",
"is1\n",
"is2"
]
},
{
"cell_type": "markdown",
"id": "smart-gnome",
"metadata": {},
"source": [
"If we move the first slider, the second one moves too. If we move the bottom slider, the top one moves too. Isn't it great?\n",
"\n",
"We can also make *directional* links. That means that if you modify the source, the target is modified too, but not viceversa.\n",
"\n",
"By the way, we can link any type of widget, as long as its fields have javascript-compatible types."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "f71e323b-ac72-42e5-8823-b768d6f9cb58",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "c4a67b75-819a-460f-9de6-7bf39a3000d9",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "9ac97149-889c-43ee-abb5-0cc006956064",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- We create the sliders\n",
"fs1 <- mkFloatSlider\n",
"fi2 <- mkIntSlider\n",
"\n",
"-- Making a directional link\n",
"link <- mkDirectionalLink\n",
"setField link Source (WidgetFieldPair fs1 FloatValue)\n",
"setField link Target (WidgetFieldPair fi2 IntValue)\n",
"\n",
"-- Displaying the sliders\n",
"fs1\n",
"fi2"
]
},
{
"cell_type": "markdown",
"id": "stone-lightweight",
"metadata": {},
"source": [
"As we expect, the bottom widget is modified when the slider in the top one changes. But the top one doesn't change if the bottom one does.\n",
"\n",
"But this \"making a widget and setting a source and setting a target\" troupe is a bit tiring. For this reason, we have the `jslink` and `jsdlink` functions, that create a link or directional link given two `WidgetFieldPair`s.\n",
"\n",
"Here we have a simple example using boolean widgets:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "91ccf115-57b4-4176-b157-0e79c27f4341",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<style>/* Styles used for the Hoogle display in the pager */\n",
".hoogle-doc {\n",
"display: block;\n",
"padding-bottom: 1.3em;\n",
"padding-left: 0.4em;\n",
"}\n",
".hoogle-code {\n",
"display: block;\n",
"font-family: monospace;\n",
"white-space: pre;\n",
"}\n",
".hoogle-text {\n",
"display: block;\n",
"}\n",
".hoogle-name {\n",
"color: green;\n",
"font-weight: bold;\n",
"}\n",
".hoogle-head {\n",
"font-weight: bold;\n",
"}\n",
".hoogle-sub {\n",
"display: block;\n",
"margin-left: 0.4em;\n",
"}\n",
".hoogle-package {\n",
"font-weight: bold;\n",
"font-style: italic;\n",
"}\n",
".hoogle-module {\n",
"font-weight: bold;\n",
"}\n",
".hoogle-class {\n",
"font-weight: bold;\n",
"}\n",
".get-type {\n",
"color: green;\n",
"font-weight: bold;\n",
"font-family: monospace;\n",
"display: block;\n",
"white-space: pre-wrap;\n",
"}\n",
".show-type {\n",
"color: green;\n",
"font-weight: bold;\n",
"font-family: monospace;\n",
"margin-left: 1em;\n",
"}\n",
".mono {\n",
"font-family: monospace;\n",
"display: block;\n",
"}\n",
".err-msg {\n",
"color: red;\n",
"font-style: italic;\n",
"font-family: monospace;\n",
"white-space: pre;\n",
"display: block;\n",
"}\n",
"#unshowable {\n",
"color: red;\n",
"font-weight: bold;\n",
"}\n",
".err-msg.in.collapse {\n",
"padding-top: 0.7em;\n",
"}\n",
".highlight-code {\n",
"white-space: pre;\n",
"font-family: monospace;\n",
"}\n",
".suggestion-warning { \n",
"font-weight: bold;\n",
"color: rgb(200, 130, 0);\n",
"}\n",
".suggestion-error { \n",
"font-weight: bold;\n",
"color: red;\n",
"}\n",
".suggestion-name {\n",
"font-weight: bold;\n",
"}\n",
"</style><span class='get-type'>jsdlink :: WidgetFieldPair -> WidgetFieldPair -> IO DirectionalLink</span>"
],
"text/plain": [
"jsdlink :: WidgetFieldPair -> WidgetFieldPair -> IO DirectionalLink"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "12cf4ada-4fc9-48c1-981e-ab7121aa9efe",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e11c0f79-775d-4597-9990-7496c00334bb",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e1690adb-30eb-4cfc-913f-33ad3133aa5b",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
":t jsdlink\n",
"chk <- mkCheckBox\n",
"tgb <- mkToggleButton\n",
"valid <- mkValid\n",
"\n",
"-- The Link widget cannot be displayed, so we ignore the return value\n",
"_ <- jslink (WidgetFieldPair chk BoolValue) (WidgetFieldPair tgb BoolValue)\n",
"_ <- jsdlink (WidgetFieldPair chk BoolValue) (WidgetFieldPair valid BoolValue)\n",
"\n",
"chk\n",
"tgb\n",
"valid"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Haskell",
"language": "haskell",
"name": "haskell"
},
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"mimetype": "text/x-haskell",
"name": "haskell",
"pygments_lexer": "Haskell",
"version": "8.10.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}