Merge pull request #1246 from daviddavo/master

Updated sample widget Notebooks
This commit is contained in:
Vaibhav Sagar 2021-08-16 02:00:37 +10:00 committed by GitHub
commit dfcbe59c76
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 2830 additions and 3055 deletions

View File

@ -1,5 +1,8 @@
# ChangeLog for `ihaskell-widgets`
## `v0.3.1.0`
+ Added ChangeHandlers to ColorPicker and DatePicker
## `v0.3.0.0`
> Revamped to be compatible with Widget Messaging Protocol, version 2

View File

@ -103,106 +103,9 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"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><div class=\"suggestion-name\" style=\"clear:both;\">Unused LANGUAGE pragma</div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Found:</div><div class=\"highlight-code\" id=\"haskell\">{-# LANGUAGE OverloadedStrings #-}</div></div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Why Not:</div><div class=\"highlight-code\" id=\"haskell\"></div></div>"
],
"text/plain": [
"Line 1: Unused LANGUAGE pragma\n",
"Found:\n",
"{-# LANGUAGE OverloadedStrings #-}\n",
"Why not:"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"{-# LANGUAGE OverloadedStrings #-}\n",
"import IHaskell.Display.Widgets"
@ -234,107 +137,9 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"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'>setField :: forall (f :: Field) (w :: WidgetType).\n",
"(RecElem Rec f f (WidgetFields w) (WidgetFields w) (RIndex f (WidgetFields w)), IHaskellWidget (IPythonWidget w), ToPairs (Attr f)) =>\n",
"IPythonWidget w -> SField f -> FieldType f -> IO ()</span>"
],
"text/plain": [
"setField :: forall (f :: Field) (w :: WidgetType).\n",
"(RecElem Rec f f (WidgetFields w) (WidgetFields w) (RIndex f (WidgetFields w)), IHaskellWidget (IPythonWidget w), ToPairs (Attr f)) =>\n",
"IPythonWidget w -> SField f -> FieldType f -> IO ()"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
":t setField"
]
@ -352,103 +157,9 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": null,
"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'>getField :: forall (f :: Field) (w :: WidgetType). RecElem Rec f f (WidgetFields w) (WidgetFields w) (RIndex f (WidgetFields w)) => IPythonWidget w -> SField f -> IO (FieldType f)</span>"
],
"text/plain": [
"getField :: forall (f :: Field) (w :: WidgetType). RecElem Rec f f (WidgetFields w) (WidgetFields w) (RIndex f (WidgetFields w)) => IPythonWidget w -> SField f -> IO (FieldType f)"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
":t getField"
]
@ -469,103 +180,9 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"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'>properties :: forall (w :: WidgetType). IPythonWidget w -> IO ()</span>"
],
"text/plain": [
"properties :: forall (w :: WidgetType). IPythonWidget w -> IO ()"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
":t properties"
]
@ -581,28 +198,9 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"3"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"abc\""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"-- Showables\n",
"1 + 2\n",
@ -618,103 +216,9 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"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'>display :: forall a. IHaskellDisplay a => a -> IO Display</span>"
],
"text/plain": [
"display :: forall a. IHaskellDisplay a => a -> IO Display"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"import IHaskell.Display\n",
":t display"
@ -742,103 +246,9 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": null,
"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'>closeWidget :: forall w. IHaskellWidget w => w -> IO ()</span>"
],
"text/plain": [
"closeWidget :: forall w. IHaskellWidget w => w -> IO ()"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
":t closeWidget"
]
@ -861,103 +271,9 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": null,
"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'>button :: Button</span>"
],
"text/plain": [
"button :: Button"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"button <- mkButton -- Construct a Button\n",
":t button"
@ -972,21 +288,9 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b0945886-50e1-411a-b282-910cb4b7ccac",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"button -- Display the button"
]
@ -1000,35 +304,9 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"ViewModule ::: Text\n",
"ViewModuleVersion ::: Text\n",
"ModelModule ::: Text\n",
"ModelModuleVersion ::: Text\n",
"ModelName ::: Text\n",
"ViewName ::: Text\n",
"DOMClasses ::: [Text]\n",
"Tabbable ::: Maybe Bool\n",
"Tooltip ::: Maybe Text\n",
"Layout ::: IPythonWidget 'LayoutType\n",
"DisplayHandler ::: IO ()\n",
"Description ::: Text\n",
"Disabled ::: Bool\n",
"Icon ::: Text\n",
"ButtonStyle ::: ButtonStyleValue\n",
"StyleButton ::: IPythonWidget 'ButtonStyleType\n",
"ClickHandler ::: IO ()"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"-- The button widget has many properties.\n",
"properties button"
@ -1043,13 +321,13 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import qualified IHaskell.Display.Widgets.Layout as L\n",
"btnStyle <- getField button StyleButton\n",
"btnLayout <- getField button Layout"
"btnLayout <- getField button Layout\n",
"setField btnLayout L.Width $ Just \"100%\""
]
},
{
@ -1061,31 +339,15 @@
},
{
"cell_type": "code",
"execution_count": 27,
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"setField button Description \"Click Me (._.\\\")\"\n",
"setField button ButtonStyle SuccessButton\n",
"-- setField button BorderStyle RidgeBorder\n",
"-- setField button BorderWidth 20\n",
"-- setField button BorderRadius 30\n",
"-- setField button Padding 10\n",
"-- setField button Height 125\n",
"setField btnStyle FontWeight BoldWeight\n",
"setField btnStyle ButtonColor $ Just \"blue\"\n",
"setField btnLayout L.Height $ Just \"7em\"\n",
"\n",
"setField button StyleButton btnStyle\n",
"-- setField button FontSize 30"
"setField btnLayout L.Border $ Just \"ridge 2px\"\n",
"setField btnLayout L.Padding $ Just \"10\"\n",
"setField btnLayout L.Height $ Just \"7em\""
]
},
{
@ -1097,21 +359,9 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b0945886-50e1-411a-b282-910cb4b7ccac",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"setField button ClickHandler $ putStrLn \"fO_o\"\n",
"button -- Displaying again for convenience"
@ -1121,12 +371,16 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Now try clicking the button, and see the output. If we try to do console input, an error occurs."
"Now try clicking the button, and see the output.\n",
"\n",
"> Note: If you display to stdout using Jupyter Lab, it will be displayed in a log entry, not as the cell output.\n",
"\n",
"We can't do console input, though, but you can always use another widget! See the other notebooks with examples for more information"
]
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [

View File

@ -22,11 +22,108 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"metadata": {
"tags": []
},
"outputs": [],
"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><div class=\"suggestion-name\" style=\"clear:both;\">Unused LANGUAGE pragma</div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Found:</div><div class=\"highlight-code\" id=\"haskell\">{-# LANGUAGE OverloadedStrings #-}</div></div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Why Not:</div><div class=\"highlight-code\" id=\"haskell\"></div></div>"
],
"text/plain": [
"Line 1: Unused LANGUAGE pragma\n",
"Found:\n",
"{-# LANGUAGE OverloadedStrings #-}\n",
"Why not:"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"{-# LANGUAGE OverloadedStrings #-}\n",
"{-# LANGUAGE FlexibleContexts #-}\n",
@ -39,12 +136,15 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### Simple demonstration"
"### Simple demonstration\n",
"We are going to create one of each widget.\n",
"\n",
"The valid widget doesn't receive any input, but it displays the status of a boolean variable."
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 2,
"metadata": {
"jupyter": {
"outputs_hidden": false
@ -59,25 +159,59 @@
"tgb <- mkToggleButton\n",
"\n",
"-- Valid widget: Displaying booleans conveniently\n",
"vld <- mkValidWidget"
"vld <- mkValid"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Below, we represent one boolean using a checkbox, and the other using a toggle button. The logical and (`&&`) of the two is displayed below."
"Below, we represent one boolean using a checkbox, and the other using a toggle button. The valid widget displays the result of applying the logical and (`&&`) between the two."
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 3,
"metadata": {
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "f86799d9-7bda-4dcb-885a-d65217634d67",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "71753836-ad8a-495f-9257-280feb66fcf5",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "14bd1aef-8479-43a2-8a10-d6a24561886b",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- Display the widgets\n",
"setField tgb Description \"Button\"\n",
@ -86,26 +220,38 @@
"vld"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To make the `Valid` widget display the result of the computation, we have to get the value of the Checkbox and the value of the ToggleButton, and then set the value of the Valid widget to the result."
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"getField chk BoolValue >>= setField chk BoolValue . not\n",
"getField tgb BoolValue >>= setField tgb BoolValue . not"
"b1 <- getField chk BoolValue\n",
"b2 <- getField tgb BoolValue\n",
"setField vld BoolValue (b1 && b2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `BoolValue` field represents the underlying boolean value."
"You can change the value of the widgets clicking in them, and then run the cell above again. If both widgets are checked, the valid widget should appear with a green check.\n",
"\n",
"But having to run the cell every time we click on the widgets is a bit cumbersome... Why not making it change auto*magic*ally? To do this, we will use a **handler**. A *handler* is a method that is called every time something happens. E.g: every time the button is clicked, or every time its associated value is changed on the frontend. These handlers are functions of type `IO ()`.\n",
"\n",
"Now, we are going to create a handler that is called every time one of the two widget changes and updates the `Valid` widget. We will also set a useful description."
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 5,
"metadata": {
"jupyter": {
"outputs_hidden": false
@ -113,20 +259,18 @@
},
"outputs": [],
"source": [
"setField chk Description \"Bool 1: \"\n",
"setField tgb Description \"Bool 2\"\n",
"setField chk Description \"b1\"\n",
"setField tgb Description \"b2\"\n",
"setField vld Description \"b1 && b2:\"\n",
"\n",
" -- Cosmetic changes\n",
"setField vld Description \"Bool 1 && Bool 2\"\n",
"\n",
" -- And (&&) the two values, and send output to html widget\n",
"setHandler w = setField w ChangeHandler $ do\n",
"ourBoolHandler :: IO ()\n",
"ourBoolHandler = do\n",
" b1 <- getField chk BoolValue\n",
" b2 <- getField tgb BoolValue\n",
" setField vld BoolValue (b1 && b2)\n",
"\n",
"setHandler chk\n",
"setHandler tgb"
"setField chk ChangeHandler ourBoolHandler\n",
"setField tgb ChangeHandler ourBoolHandler"
]
},
{
@ -147,7 +291,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 6,
"metadata": {
"jupyter": {
"outputs_hidden": false
@ -158,7 +302,8 @@
"-- First, some library functions\n",
"import Control.Monad (replicateM, forM_)\n",
"import Data.IORef\n",
"import IHaskell.Display (plain)"
"import IHaskell.Display (plain)\n",
"import qualified IHaskell.Display.Widgets.Layout as L"
]
},
{
@ -170,7 +315,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 7,
"metadata": {
"jupyter": {
"outputs_hidden": false
@ -184,7 +329,7 @@
"setField sign Description \"Negative\"\n",
"forM_ bits $ \\t -> do\n",
" setField t ButtonStyle PrimaryButton\n",
" setField t BorderRadius 20"
" -- setField t BorderRadius 20"
]
},
{
@ -196,39 +341,295 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 8,
"metadata": {
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "212247f8-aea0-4eb9-86b9-40b01873e622",
"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"
}
],
"source": [
"box <- mkFlexBox\n",
"out <- mkHTMLWidget\n",
"box <- mkVBox\n",
"out <- mkHTML\n",
"\n",
"-- Sub-containers\n",
"box1 <- mkFlexBox\n",
"box1 <- mkBox\n",
"setField box1 Children [ChildWidget sign, ChildWidget out]\n",
"box2 <- mkFlexBox\n",
"box2 <- mkBox\n",
"setField box2 Children (map ChildWidget $ reverse bits)\n",
"\n",
"-- Add widgets to the container\n",
"setField box Children (map ChildWidget [box1, box2])\n",
"setField box Orientation VerticalOrientation\n",
"\n",
"-- Add some UI chrome\n",
"setField box BoxStyle InfoBox\n",
"setField box BorderRadius 20\n",
"setField out BorderStyle GrooveBorder\n",
"setField out BorderRadius 20\n",
"setField out BorderWidth 4\n",
"setField out Width 100\n",
"setField out Height 30\n",
"setField out Margin 10\n",
"setField sign Padding 10\n",
"setField box2 Padding 10\n",
"setField box2 Pack BaselineLocation\n",
"layout <- getField out Layout\n",
"setField layout L.Width $ Just \"100px\"\n",
"setField layout L.Height $ Just \"30px\"\n",
"setField layout L.Margin $ Just \"10px\"\n",
"setField layout L.Border $ Just \"4px groove\"\n",
"\n",
"-- Display the container\n",
"box"
@ -243,13 +644,21 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 9,
"metadata": {
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [],
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import Control.Arrow (first, second)\n",
"\n",
@ -268,6 +677,8 @@
" modifyIORef val (second not)\n",
" -- Redraw output\n",
" readIORef val >>= refresh\n",
" \n",
"setField out StringValue \"<div align=\\\"center\\\"><b>%d</b></div>\"\n",
"\n",
"forM_ (zip bits (iterate (*2) 1)) $ \\(t, n) -> do\n",
" setField t Description \"0\"\n",
@ -277,6 +688,13 @@
" modifyIORef val (first $ if f then (+n) else (\\x->x-n))\n",
" readIORef val >>= refresh"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {

View File

@ -241,7 +241,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"#### `Box` and `FlexBox`"
"#### `Box`, `VBox`, `HBox` and `GridBox`"
]
},
{
@ -250,7 +250,7 @@
"metadata": {},
"outputs": [],
"source": [
"-- Create new Box and FlexBox\n",
"-- Create new Boxes and GridBox\n",
"box <- mkBox\n",
"vbox <- mkVBox\n",
"hbox <- mkHBox\n",
@ -261,7 +261,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"By default, boxes have a horizontal orientation. Thus adding some widgets to them lays them out horizontally."
"`Box` and `HBox` have a horizontal orientation. This means that adding new widgets to them lays them out horizontally. In contrast, `VBox` lays them vertically. `GridBox` lets you display the widgets in a grid. "
]
},
{
@ -272,7 +272,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "0fb6356c-d874-4914-9255-653cd4379bbe",
"model_id": "0417bfce-fdb1-4f01-9d03-a470e5aba96e",
"version_major": 2,
"version_minor": 0
}
@ -283,7 +283,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e3b57907-eb05-48c2-916e-d73c9e6759c4",
"model_id": "7477f34f-e4ce-4320-9316-3d542d3a3c08",
"version_major": 2,
"version_minor": 0
}
@ -294,7 +294,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e9dfc367-a08c-46b5-a82a-e428efc6be41",
"model_id": "b0876039-5c34-48c7-968f-e8d99811b177",
"version_major": 2,
"version_minor": 0
}
@ -305,7 +305,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "0414ff9d-5247-4e5d-b8c9-a4bf6c056794",
"model_id": "7670dab0-ab1d-4016-a30f-7f0e3a969ebb",
"version_major": 2,
"version_minor": 0
}
@ -346,22 +346,25 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"You might be thinking that there is no difference between `Box` and `FlexBox`, but that's not true.\n",
"You might be thinking that there is no difference between `VBox` and `GridBox`, but that's not true.\n",
"\n",
"Following are some differences:\n",
"`VBox` has always one column, while `GridBox` lets you modify the number of colums if you modify its css.\n",
"\n",
"+ `Box` is always horizontal, whereas `FlexBox` has a configurable `Orientation`.\n",
"+ `FlexBox` is flexible, and the flexibility is determined by its `Flex` field (0 to 2).\n",
"+ `FlexBox` also has explicit `Pack` and `Align` fields.\n",
"Let's make a 2x2 grid on `GridBox`. To accomplish our goal, we need to obtain it's associated `Layout` and modify its `GridTemplateColumns` field.\n",
"\n",
"Let's see these differences in action:"
"> You can get a complete and updated CSS grid layout reference at [Mozilla's docs](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout)"
]
},
{
"cell_type": "markdown",
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"The error means that the widget doesn't possess the `Orientation` property."
"import qualified IHaskell.Display.Widgets.Layout as L\n",
"\n",
"layout <- getField gbox Layout\n",
"setField layout L.GridTemplateColumns $ Just \"repeat(2,1fr)\""
]
},
{
@ -380,12 +383,12 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"acc <- mkAccordion\n",
"tab <- mkTabWidget"
"tab <- mkTab"
]
},
{
@ -397,13 +400,13 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "2b342100-17b1-477d-9d8c-d5aec446fcc2",
"model_id": "e9cdff5d-1630-4845-a986-de1ac490e55e",
"version_major": 2,
"version_minor": 0
}
@ -414,58 +417,13 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "fbae112a-7d07-48a9-9087-d49abcb339c4",
"model_id": "36172e5a-879c-4584-a74b-17a5c121517a",
"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"
}
],
"source": [
@ -486,7 +444,40 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Both the widgets are similar, the only major difference is in the orientation. `Accordion` is vertical, whereas `TabWidget` is horizontal."
"Both the widgets are similar, the only major difference is in the orientation. `Accordion` is vertical, whereas `TabWidget` is horizontal. We can get or set the selected tab with the field `SelectedIndex :: Maybe Integer`. If it's set to `Nothing`, then the accordion/tabs are all closed."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Nothing"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"Nothing"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"getField acc SelectedIndex\n",
"getField tab SelectedIndex\n",
"\n",
"-- Let's try closing them\n",
"setField tab SelectedIndex Nothing\n",
"setField acc SelectedIndex Nothing"
]
}
],

View File

@ -5,27 +5,17 @@
"id": "6513368f-ebd6-4c00-b69b-7004c3189fc6",
"metadata": {},
"source": [
"## Controller widgets"
"## Controller widgets\n",
"\n",
"I'm sorry, but this widget is still Work In Progress"
]
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": null,
"id": "1db1ebee-6896-4a92-9a9c-4d0c0e2fef34",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"{-# LANGUAGE OverloadedStrings #-}\n",
"controller <- mkController\n",
@ -35,47 +25,10 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"id": "463d9488-8941-4e4a-aa47-83ba2f879368",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"0.0"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"\""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"getField controller Connected\n",
"getField controller Name\n",
@ -83,27 +36,6 @@
"getField controller Mapping\n",
"getField controller Buttons"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "a19e8443-2f74-47b6-b17a-d860289bc20b",
"metadata": {},
"outputs": [
{
"ename": "",
"evalue": "",
"header": "MessageHeader {mhIdentifiers = [\"b1a38970-0242-4f9b-be4a-a439b9458ed4\"], mhParentHeader = Just (MessageHeader {mhIdentifiers = [\"b1a38970-0242-4f9b-be4a-a439b9458ed4\"], mhParentHeader = Nothing, mhMetadata = Metadata (fromList [(\"recordTiming\",Bool False),(\"deletedCells\",Array []),(\"cellId\",String \"a19e8443-2f74-47b6-b17a-d860289bc20b\")]), mhMessageId = UUID {uuidToString = \"e9dc7aff-4bd9-4419-91ee-5ec41a25ed5d\"}, mhSessionId = UUID {uuidToString = \"b1a38970-0242-4f9b-be4a-a439b9458ed4\"}, mhUsername = \"\", mhMsgType = ExecuteRequestMessage, mhBuffers = []}), mhMetadata = Metadata (fromList []), mhMessageId = UUID {uuidToString = \"b3701acd-6179-45ab-9eca-9ecacfdb5be8\"}, mhSessionId = UUID {uuidToString = \"b1a38970-0242-4f9b-be4a-a439b9458ed4\"}, mhUsername = \"\", mhMsgType = ExecuteErrorMessage, mhBuffers = []}",
"output_type": "error",
"traceback": [
"The field SName is read only\nCallStack (from HasCallStack):\n error, called at src/IHaskell/Display/Widgets/Types.hs:953:21 in ihaskell-widgets-0.3.0.0-6i4Ez3HICSV5LpRY8SD96:IHaskell.Display.Widgets.Types"
]
}
],
"source": [
"-- Read only\n",
"setField controller Name \"AAAAAAAA\""
]
}
],
"metadata": {

View File

@ -1,268 +0,0 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "089cfc9a-ee04-4a75-b519-e1b1ef4c5ed5",
"metadata": {},
"source": [
"The layout widget is a widget that adheres to any other widget"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "3643e44d-0220-46be-867e-8e7781fb7bbe",
"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><div class=\"suggestion-name\" style=\"clear:both;\">Unused LANGUAGE pragma</div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Found:</div><div class=\"highlight-code\" id=\"haskell\">{-# LANGUAGE OverloadedStrings #-}</div></div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Why Not:</div><div class=\"highlight-code\" id=\"haskell\"></div></div>"
],
"text/plain": [
"Line 1: Unused LANGUAGE pragma\n",
"Found:\n",
"{-# LANGUAGE OverloadedStrings #-}\n",
"Why not:"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"{-# LANGUAGE OverloadedStrings #-}\n",
"import IHaskell.Display.Widgets\n",
"import IHaskell.Display.Widgets.Layout\n",
"import Data.Text as T"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "d8430ed3-0e24-4057-8230-73c47fa75793",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e3fec42f-c887-4ecf-922d-b4a3754cee5a",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"button <- mkButton\n",
"setField button Description \"Click me!\"\n",
"button"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "08d9c91c-8065-4a66-b564-b225e316f379",
"metadata": {},
"outputs": [],
"source": [
"layout <- mkLayout\n",
"setField button Layout $ Just layout"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "6357dffb-f70e-475e-a007-41211d495042",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"ModelModule ::: Text\n",
"ModelModuleVersion ::: Text\n",
"ModelName ::: Text\n",
"ViewModule ::: Text\n",
"ViewModuleVersion ::: Text\n",
"ViewName ::: Text\n",
"LAlignContent ::: Maybe [Char]\n",
"LAlignItems ::: Maybe [Char]\n",
"LAlignSelf ::: Maybe [Char]\n",
"LBorder ::: Maybe [Char]\n",
"LBottom ::: Maybe [Char]\n",
"LDisplay ::: Maybe [Char]\n",
"LFlex ::: Maybe [Char]\n",
"LFlexFlow ::: Maybe [Char]\n",
"LGridArea ::: Maybe [Char]\n",
"LGridAutoColumns ::: Maybe [Char]\n",
"LGridAutoFlow ::: Maybe [Char]\n",
"LGridAutoRows ::: Maybe [Char]\n",
"LGridColumn ::: Maybe [Char]\n",
"LGridGap ::: Maybe [Char]\n",
"LGridRow ::: Maybe [Char]\n",
"LGridTemplateAreas ::: Maybe [Char]\n",
"LGridTemplateColumns ::: Maybe [Char]\n",
"LGridTemplateRows ::: Maybe [Char]\n",
"LHeight ::: Maybe [Char]\n",
"LJustifyContent ::: Maybe [Char]\n",
"LJustifyItems ::: Maybe [Char]\n",
"LLeft ::: Maybe [Char]\n",
"LMargin ::: Maybe [Char]\n",
"LMaxHeight ::: Maybe [Char]\n",
"LMaxWidth ::: Maybe [Char]\n",
"LMinHeight ::: Maybe [Char]\n",
"LMinWidth ::: Maybe [Char]\n",
"LOrder ::: Maybe [Char]\n",
"LOverflow ::: Maybe [Char]\n",
"LOverflowX ::: Maybe [Char]\n",
"LOverflowY ::: Maybe [Char]\n",
"LPadding ::: Maybe [Char]\n",
"LRight ::: Maybe [Char]\n",
"LTop ::: Maybe [Char]\n",
"LVisibility ::: Maybe [Char]\n",
"LWidth ::: Maybe [Char]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"properties layout"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "ef00e9aa-3f48-42ff-bb45-9f59b09e78e4",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e3fec42f-c887-4ecf-922d-b4a3754cee5a",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"setField layout Border $ Just \"3px solid red\"\n",
"button"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "141277e9-4082-4b93-a597-9f34c4bfcf2c",
"metadata": {},
"outputs": [],
"source": [
"setField layout Visibility $ Just \"unset\""
]
}
],
"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
}

View File

@ -0,0 +1,523 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "089cfc9a-ee04-4a75-b519-e1b1ef4c5ed5",
"metadata": {},
"source": [
"# The Layout and Style Widgets\n",
"\n",
"## The Layout widget\n",
"The layout widget is a widget that adheres to any other widget. It holds some CSS layout properties for its father widget. E.g: width and height, alignment, border..."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "3643e44d-0220-46be-867e-8e7781fb7bbe",
"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><div class=\"suggestion-name\" style=\"clear:both;\">Unused LANGUAGE pragma</div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Found:</div><div class=\"highlight-code\" id=\"haskell\">{-# LANGUAGE OverloadedStrings #-}</div></div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Why Not:</div><div class=\"highlight-code\" id=\"haskell\"></div></div>"
],
"text/plain": [
"Line 1: Unused LANGUAGE pragma\n",
"Found:\n",
"{-# LANGUAGE OverloadedStrings #-}\n",
"Why not:"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"{-# LANGUAGE OverloadedStrings #-}\n",
"import IHaskell.Display.Widgets\n",
"import qualified IHaskell.Display.Widgets.Layout as L\n",
"import Data.Text as T"
]
},
{
"cell_type": "markdown",
"id": "billion-cookbook",
"metadata": {},
"source": [
"First, we need a sample widget to modify its layout"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "d8430ed3-0e24-4057-8230-73c47fa75793",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "7d321970-3eda-40b4-818f-f468e1942fff",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"button <- mkButton\n",
"setField button Description \"Click me!\"\n",
"button"
]
},
{
"cell_type": "markdown",
"id": "supreme-ribbon",
"metadata": {},
"source": [
"Then, we get the associated Layout widget with `getField`"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "08d9c91c-8065-4a66-b564-b225e316f379",
"metadata": {},
"outputs": [],
"source": [
"layout <- getField button Layout"
]
},
{
"cell_type": "markdown",
"id": "immediate-hospital",
"metadata": {},
"source": [
"We can display all the things we can modify using the `properties` function."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "6357dffb-f70e-475e-a007-41211d495042",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"ModelModule ::: Text\n",
"ModelModuleVersion ::: Text\n",
"ModelName ::: Text\n",
"ViewModule ::: Text\n",
"ViewModuleVersion ::: Text\n",
"ViewName ::: Text\n",
"LAlignContent ::: Maybe [Char]\n",
"LAlignItems ::: Maybe [Char]\n",
"LAlignSelf ::: Maybe [Char]\n",
"LBorder ::: Maybe [Char]\n",
"LBottom ::: Maybe [Char]\n",
"LDisplay ::: Maybe [Char]\n",
"LFlex ::: Maybe [Char]\n",
"LFlexFlow ::: Maybe [Char]\n",
"LGridArea ::: Maybe [Char]\n",
"LGridAutoColumns ::: Maybe [Char]\n",
"LGridAutoFlow ::: Maybe [Char]\n",
"LGridAutoRows ::: Maybe [Char]\n",
"LGridColumn ::: Maybe [Char]\n",
"LGridGap ::: Maybe [Char]\n",
"LGridRow ::: Maybe [Char]\n",
"LGridTemplateAreas ::: Maybe [Char]\n",
"LGridTemplateColumns ::: Maybe [Char]\n",
"LGridTemplateRows ::: Maybe [Char]\n",
"LHeight ::: Maybe [Char]\n",
"LJustifyContent ::: Maybe [Char]\n",
"LJustifyItems ::: Maybe [Char]\n",
"LLeft ::: Maybe [Char]\n",
"LMargin ::: Maybe [Char]\n",
"LMaxHeight ::: Maybe [Char]\n",
"LMaxWidth ::: Maybe [Char]\n",
"LMinHeight ::: Maybe [Char]\n",
"LMinWidth ::: Maybe [Char]\n",
"LOrder ::: Maybe [Char]\n",
"LOverflow ::: Maybe [Char]\n",
"LOverflowX ::: Maybe [Char]\n",
"LOverflowY ::: Maybe [Char]\n",
"LPadding ::: Maybe [Char]\n",
"LRight ::: Maybe [Char]\n",
"LTop ::: Maybe [Char]\n",
"LVisibility ::: Maybe [Char]\n",
"LWidth ::: Maybe [Char]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"properties layout"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "ef00e9aa-3f48-42ff-bb45-9f59b09e78e4",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"setField layout L.Height $ Just \"50px\"\n",
"setField layout L.MinWidth $ Just \"70%\"\n",
"setField layout L.Padding $ Just \"10px\""
]
},
{
"cell_type": "markdown",
"id": "furnished-quantity",
"metadata": {},
"source": [
"The layout widget is most useful with the `Box` widgets, if you know how to use CSS layouts.\n",
"\n",
"## The Style Widgets\n",
"\n",
"Some widgets have some predefined styles that you can set, like buttons or sliders. But if you want more customization you have to use a Style widget. There are five kinds of style widgets:\n",
"\n",
"- `ButtonStyle`\n",
"- `DescriptionStyle`\n",
"- `ProgressStyle`\n",
"- `SliderStyle`\n",
"- `ToggleButtonsStyle`\n",
"\n",
"We are going to do an example with a slider. First, we have to create both widgets:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "widespread-precipitation",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "bfe255db-9a90-47da-9032-48440e0a0b18",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- Creating the slider\n",
"slider <- mkIntSlider\n",
"\n",
"-- Creating the style widget\n",
"style <- mkSliderStyle\n",
"\n",
"-- Displaying the slider\n",
"slider"
]
},
{
"cell_type": "markdown",
"id": "internal-movement",
"metadata": {},
"source": [
"Then, we set the Slider's style, setting the field `Style`. We have to use the `StyleWidget` constructor."
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "physical-anthony",
"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'>StyleWidget :: forall (w :: WidgetType). RecAll Attr (WidgetFields w) ToPairs => IPythonWidget w -> StyleWidget</span>"
],
"text/plain": [
"StyleWidget :: forall (w :: WidgetType). RecAll Attr (WidgetFields w) ToPairs => IPythonWidget w -> StyleWidget"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
":t StyleWidget\n",
"setField slider Style $ StyleWidget style"
]
},
{
"cell_type": "markdown",
"id": "turned-implement",
"metadata": {},
"source": [
"What happens if we set a long description?"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "chemical-applicant",
"metadata": {},
"outputs": [],
"source": [
"setField slider Description \"This is a long description\""
]
},
{
"cell_type": "markdown",
"id": "differential-trademark",
"metadata": {},
"source": [
"The description is so long, the fronted has to cut it by default. But we have our style widget to save us. "
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "relevant-intensity",
"metadata": {},
"outputs": [],
"source": [
"setField style DescriptionWidth \"14em\""
]
},
{
"cell_type": "markdown",
"id": "defensive-minutes",
"metadata": {},
"source": [
"Now the widget is very small... Let's make it a bit bigger using our layout tricks..."
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "collective-failing",
"metadata": {},
"outputs": [],
"source": [
"layout <- getField slider Layout\n",
"setField layout L.Width $ Just \"30em\""
]
},
{
"cell_type": "markdown",
"id": "ignored-nomination",
"metadata": {},
"source": [
"We can also set the color of the handle to anything we want"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "perfect-antarctica",
"metadata": {},
"outputs": [],
"source": [
"setField style HandleColor $ Just \"pink\""
]
}
],
"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
}

View File

@ -2,9 +2,448 @@
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"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": {
@ -90,42 +529,19 @@
".suggestion-name {\n",
"font-weight: bold;\n",
"}\n",
"</style><div class=\"suggestion-name\" style=\"clear:both;\">Unused LANGUAGE pragma</div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Found:</div><div class=\"highlight-code\" id=\"haskell\">{-# LANGUAGE OverloadedStrings #-}</div></div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Why Not:</div><div class=\"highlight-code\" id=\"haskell\"></div></div>"
"</style><span class='get-type'>jsdlink :: WidgetFieldPair -> WidgetFieldPair -> IO DirectionalLink</span>"
],
"text/plain": [
"Line 1: Unused LANGUAGE pragma\n",
"Found:\n",
"{-# LANGUAGE OverloadedStrings #-}\n",
"Why not:"
"jsdlink :: WidgetFieldPair -> WidgetFieldPair -> IO DirectionalLink"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"{-# LANGUAGE OverloadedStrings #-}\n",
"import IHaskell.Display.Widgets"
]
},
{
"cell_type": "markdown",
"id": "bdf75813-33a0-4b98-a41a-35b3d88bcee9",
"metadata": {},
"source": [
"# The `Link` widgets"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "107c6fc9-c1fd-433d-8719-fa3daea8bc51",
"metadata": {},
"outputs": [
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "89dcb9bc-8085-4087-8992-8c440fecee25",
"model_id": "12cf4ada-4fc9-48c1-981e-ab7121aa9efe",
"version_major": 2,
"version_minor": 0
}
@ -136,53 +552,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "a31e978c-bc60-4d4c-bf4b-f9a5962d2873",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"is1 <- mkIntSlider\n",
"is2 <- mkIntSlider\n",
"\n",
"is1\n",
"is2"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "a8334d7b-d687-49c7-a191-fa3970690e1a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"link <- mkLink\n",
"setField link Source (WidgetFieldPair is1 IntValue)\n",
"setField link Target (WidgetFieldPair is2 IntValue)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "f71e323b-ac72-42e5-8823-b768d6f9cb58",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e1eebc22-055d-4b52-b020-4fd30dea38fb",
"model_id": "e11c0f79-775d-4597-9990-7496c00334bb",
"version_major": 2,
"version_minor": 0
}
@ -193,53 +563,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "d3b37a97-0423-4ff1-969d-1e8c76946f18",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fs1 <- mkFloatSlider\n",
"fs2 <- mkFloatSlider\n",
"\n",
"fs1\n",
"fs2"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "c3a64106-3a89-4cfb-9a07-da251ebf9d1a",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"link <- mkDirectionalLink\n",
"setField link Source (WidgetFieldPair fs1 FloatValue)\n",
"setField link Target (WidgetFieldPair fs2 FloatValue)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "91ccf115-57b4-4176-b157-0e79c27f4341",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "f12e8868-2684-4ccc-b6da-60d0a30425d9",
"model_id": "e1690adb-30eb-4cfc-913f-33ad3133aa5b",
"version_major": 2,
"version_minor": 0
}
@ -248,35 +572,55 @@
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "aecf1170-0f04-4dfa-9dc1-98a751599847",
"version_major": 2,
"version_minor": 0
}
},
"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",
"_ <- jsdlink (WidgetFieldPair chk BoolValue) (WidgetFieldPair tgb BoolValue)\n",
"_ <- jslink (WidgetFieldPair chk BoolValue) (WidgetFieldPair tgb BoolValue)\n",
"_ <- jsdlink (WidgetFieldPair chk BoolValue) (WidgetFieldPair valid BoolValue)\n",
"\n",
"chk\n",
"tgb"
"tgb\n",
"valid"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ee974e80-4d83-4e3a-9496-e08756fdfd17",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {

View File

@ -5,21 +5,15 @@
"metadata": {},
"source": [
"## The `Media` Widgets\n",
"\n",
"The media widgets allow you to display images, video and audio.\n",
"\n",
"All the media widgets have a `BSValue`. It's a ByteStream value with the data to display."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### The `Image` Widget\n",
"\n",
"This widget can be used to display images, with `ImageFormat` we can set the format of the image. If we set `ImageFormat` to `IURL` and `BSValue` to the utf8-encoded URL, the online image will be displayed automatically."
]
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 3,
"metadata": {},
"outputs": [
{
@ -124,6 +118,19 @@
"import IHaskell.Display.Widgets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### The `Image` Widget\n",
"\n",
"This widget can be used to display images. It has the field `ImageFormat`, with which we can set the format of the image.\n",
"\n",
"Now we're going to download some image from the internet and display it\n",
"\n",
"If we set `ImageFormat` to `IURL` and `BSValue` to the utf8-encoded URL, the online image will be displayed automatically."
]
},
{
"cell_type": "markdown",
"metadata": {},
@ -133,7 +140,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
@ -152,13 +159,13 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b82b6c13-f47c-43cf-a801-8dc2f6abcc24",
"model_id": "5e350768-e129-4c3b-afff-31543736957d",
"version_major": 2,
"version_minor": 0
}
@ -168,10 +175,10 @@
}
],
"source": [
"png <- get \"https://imgs.xkcd.com/comics/haskell.png\"\n",
"img <- mkImageWidget\n",
"png <- get \"https://imgs.xkcd.com/comics/functional.png\"\n",
"img <- mkImage\n",
"setField img ImageFormat PNG\n",
"setField img BSValue png\n",
"setField img BSValue $ JSONByteString png\n",
"img"
]
},
@ -190,7 +197,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "cb2129d6-418d-4c05-873b-34befb693555",
"model_id": "7cd95391-858f-43ec-b014-bc1fc6e53241",
"version_major": 2,
"version_minor": 0
}
@ -200,9 +207,9 @@
}
],
"source": [
"imgurl <- mkImageWidget\n",
"imgurl <- mkImage\n",
"setField imgurl ImageFormat IURL\n",
"setField imgurl BSValue \"https://imgs.xkcd.com/comics/functional.png\"\n",
"setField imgurl BSValue \"https://imgs.xkcd.com/comics/haskell.png\"\n",
"imgurl"
]
},
@ -217,13 +224,13 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b88a1b8c-a022-47fa-b417-27e63640f3f1",
"model_id": "3be8c81c-a522-4e6a-9529-9fe6f3113b85",
"version_major": 2,
"version_minor": 0
}
@ -233,9 +240,9 @@
}
],
"source": [
"video <- mkVideoWidget\n",
"video <- mkVideo\n",
"mp4 <- get \"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4\"\n",
"setField video BSValue mp4\n",
"setField video BSValue $ JSONByteString mp4\n",
"video"
]
},
@ -253,7 +260,7 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
@ -271,13 +278,13 @@
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "0baa58f4-b663-489d-b18e-af51da067342",
"model_id": "7a887e98-b625-46cd-ad74-1b4b3cfd767a",
"version_major": 2,
"version_minor": 0
}
@ -287,7 +294,7 @@
}
],
"source": [
"audio <- mkAudioWidget\n",
"audio <- mkAudio\n",
"setField audio BSValue \"https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3\"\n",
"setField audio AudioFormat AURL\n",
"setField audio Loop False\n",

View File

@ -151,7 +151,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "8aba3dd6-68f7-40f1-ae02-86f54f82d1c8",
"model_id": "0f03d310-6e35-4635-bff5-1b34d78661e4",
"version_major": 2,
"version_minor": 0
}
@ -162,48 +162,13 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "3fe2a7ef-b423-4467-813a-8d5b5aa5b64b",
"model_id": "b0535a35-d10c-4887-9559-167cf2e8ab3c",
"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": [
@ -222,13 +187,13 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"4"
"0"
]
},
"metadata": {},
@ -237,7 +202,7 @@
{
"data": {
"text/plain": [
"3.0"
"0.0"
]
},
"metadata": {},
@ -258,13 +223,13 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"7.0"
"0.0"
]
},
"metadata": {},
@ -287,7 +252,7 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
@ -306,7 +271,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
@ -323,13 +288,13 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "8aba3dd6-68f7-40f1-ae02-86f54f82d1c8",
"model_id": "0f03d310-6e35-4635-bff5-1b34d78661e4",
"version_major": 2,
"version_minor": 0
}
@ -340,48 +305,13 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "3fe2a7ef-b423-4467-813a-8d5b5aa5b64b",
"model_id": "b0535a35-d10c-4887-9559-167cf2e8ab3c",
"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": [
@ -404,13 +334,13 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "2602a0da-b65c-495c-b5b9-c09ff8d730c1",
"model_id": "653d0c7e-1661-48e2-8844-26aa0bb95bc2",
"version_major": 2,
"version_minor": 0
}
@ -421,88 +351,13 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "92af55a4-825c-4fa9-89af-bb0027e17945",
"model_id": "d52da821-8234-40fa-87e4-f20ef6975311",
"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"
}
],
"source": [
@ -545,17 +400,9 @@
},
{
"cell_type": "code",
"execution_count": 22,
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"outputs": [],
"source": [
"ins <- mkIntSlider\n",
"irs <- mkIntRangeSlider\n",
@ -570,13 +417,13 @@
},
{
"cell_type": "code",
"execution_count": 23,
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "649cca43-5d11-42a0-aeab-a2c5030fb53e",
"model_id": "9ef1b79b-2fbf-421b-a340-085f5c406b96",
"version_major": 2,
"version_minor": 0
}
@ -587,7 +434,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b6af50a2-24f1-4db7-b2de-86b9aa85e88a",
"model_id": "7a4e0717-fd52-45ab-9fd5-6513b1686d3a",
"version_major": 2,
"version_minor": 0
}
@ -598,7 +445,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "21e40bb6-31d5-4dc7-bffe-c33f1bee04cf",
"model_id": "377be754-1e66-4630-91b6-dbd4878f22df",
"version_major": 2,
"version_minor": 0
}
@ -609,7 +456,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "f67f4fa5-92c7-4f69-bc0f-213fb5766de3",
"model_id": "358e4973-0d79-4b1a-ac7a-bddc88e661cf",
"version_major": 2,
"version_minor": 0
}
@ -620,288 +467,13 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "64ef3a86-06e4-43ca-9fdf-c2a198af09df",
"model_id": "2ebd3f22-c9c2-4948-a6b8-e301f4f14baa",
"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"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
@ -921,13 +493,13 @@
},
{
"cell_type": "code",
"execution_count": 24,
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(41,75)"
"(25,75)"
]
},
"metadata": {},
@ -936,7 +508,7 @@
{
"data": {
"text/plain": [
"(13.9,38.0)"
"(0.0,1.0)"
]
},
"metadata": {},
@ -950,7 +522,7 @@
},
{
"cell_type": "code",
"execution_count": 25,
"execution_count": 12,
"metadata": {},
"outputs": [
{
@ -975,13 +547,13 @@
},
{
"cell_type": "code",
"execution_count": 27,
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b6af50a2-24f1-4db7-b2de-86b9aa85e88a",
"model_id": "7a4e0717-fd52-45ab-9fd5-6513b1686d3a",
"version_major": 2,
"version_minor": 0
}
@ -992,23 +564,13 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "8aba3dd6-68f7-40f1-ae02-86f54f82d1c8",
"model_id": "0f03d310-6e35-4635-bff5-1b34d78661e4",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
@ -1032,7 +594,7 @@
},
{
"cell_type": "code",
"execution_count": 28,
"execution_count": 14,
"metadata": {},
"outputs": [
{
@ -1058,7 +620,7 @@
},
{
"cell_type": "code",
"execution_count": 29,
"execution_count": 15,
"metadata": {},
"outputs": [
{
@ -1084,7 +646,7 @@
},
{
"cell_type": "code",
"execution_count": 34,
"execution_count": 16,
"metadata": {},
"outputs": [
{
@ -1122,13 +684,13 @@
},
{
"cell_type": "code",
"execution_count": 35,
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "4df8101c-11af-4b44-9e2c-488121c9db16",
"model_id": "fdc5d66a-a7ad-4b84-bd2e-24630eb4adc0",
"version_major": 2,
"version_minor": 0
}
@ -1144,7 +706,7 @@
},
{
"cell_type": "code",
"execution_count": 36,
"execution_count": 18,
"metadata": {},
"outputs": [
{
@ -1173,7 +735,7 @@
},
{
"cell_type": "code",
"execution_count": 40,
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
@ -1189,13 +751,13 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "3c454506-f79f-4811-8d17-936a479ea4c2",
"model_id": "c615249d-1c83-4e21-8b96-4183cab62964",
"version_major": 2,
"version_minor": 0
}
@ -1214,7 +776,7 @@
},
{
"cell_type": "code",
"execution_count": 39,
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
@ -1237,13 +799,13 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "cf60cbfb-e624-4672-8840-c66409463806",
"model_id": "7be98900-12ca-4f6b-8837-0b6679eb933a",
"version_major": 2,
"version_minor": 0
}

View File

@ -692,7 +692,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "7b6bcbd4-048e-4110-8d2d-fd2a837a2409",
"model_id": "65475610-8b2f-46a6-a3a4-5aa92af8466f",
"version_major": 2,
"version_minor": 0
}
@ -702,21 +702,35 @@
}
],
"source": [
"o <- mkOutputWidget\n",
"o <- mkOutput\n",
"o"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can append plaintext either to the stdout or the stderr with `appendStdout` and `appendStderr`. We can also clear the output widget with `clearOutput`."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"setField o Outputs []\n",
"clearOutput o\n",
"appendStdout o \"Hello World!\"\n",
"appendStderr o \"Goodbye World!\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you want to display anything other than text you'll have to use the `appendDisplay` function, which allows you to display anything displayable (i.e. anything of the `IHaskellDisplay` class)"
]
},
{
"cell_type": "code",
"execution_count": 4,
@ -818,44 +832,30 @@
],
"source": [
":t appendDisplay\n",
"imgurl <- mkImageWidget\n",
"imgurl <- mkImage\n",
"setField imgurl ImageFormat IURL\n",
"setField imgurl BSValue \"https://imgs.xkcd.com/comics/functional.png\"\n",
"appendDisplay o imgurl"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"clearOutput o"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `Output` widget is meant to be used through the functions:\n",
"\n",
"+ `appendOutput`: Append more output to the widget.\n",
"+ `appendStderr`:\n",
"+ `appendDisplay`:\n",
"+ `clearOutput`: Clear the output widget ASAP.\n",
"+ `clearOutput_`: Clear the output widget on next use of `appendOutput`.\n",
"+ `replaceOutput`: Clear then append."
"We can append rich text using the `html` function, that transforms a `String` string to `DisplayData`. Pretty cool, isn't it?"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"execution_count": 5,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "8071df04-0159-4e23-9230-f45e72b33a48",
"model_id": "2cc7d38f-dd7f-429d-b14c-eafa2465e4c1",
"version_major": 2,
"version_minor": 0
}
@ -866,11 +866,11 @@
],
"source": [
"import Text.Printf\n",
"o <- mkOutputWidget -- Make output widget\n",
"o <- mkOutput -- Make output widget\n",
"o -- Display output widget\n",
"\n",
"fmt = \"<font color=\\\"%s\\\"><marquee direction=\\\"%s\\\" style=\\\"background:%s\\\">%s</marquee></font>\"\n",
"add fg bg dir txt = appendOutput o $ html $ printf fmt fg dir bg txt\n",
"add fg bg dir txt = appendDisplay o $ html $ printf fmt fg dir bg txt\n",
"\n",
"add \"WHITE\" \"RED\" \"left\" \"The <b>OUTPUT</b> Widget\"\n",
"add \"WHITE\" \"BLUE\" \"right\" \"Is really <b>SIMPLE</b>\"\n",
@ -881,7 +881,44 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Currently, the output widget doesn't support displaying other widgets inside it. It does so in IPython, but not in IHaskell."
"The output widget is able to display *anything*, even **widgets**!"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "0d5927fc-7a68-4603-beec-0c6376f43707",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- Creating the output widget\n",
"o <- mkOutput\n",
"o\n",
"\n",
"-- Making a button\n",
"button <- mkButton\n",
"setField button Description \"Hi!\"\n",
"\n",
"-- Appending the button to the display\n",
"appendDisplay o button"
]
}
],

View File

@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 30,
"id": "c6eaf03d-cf32-448f-949f-1dcafeed8e56",
"metadata": {},
"outputs": [
@ -104,19 +104,38 @@
}
],
"source": [
"{-# LANGUAGE OverloadedStrings #-}"
"{-# LANGUAGE OverloadedStrings #-}\n",
"import Data.Text\n",
"import Text.Printf\n",
"import IHaskell.Display.Widgets"
]
},
{
"cell_type": "markdown",
"id": "alert-arrangement",
"metadata": {},
"source": [
"# The Picker widgets\n",
"\n",
"Here we have two widgets that allow you input of special inputs, like dates or colors. They are the `ColorPicker` and `DatePicker`. These widgets work on almost every modern web browser.\n",
"\n",
"## `ColorPicker`\n",
"\n",
"Is a widget that displays a color wheel and allows you to select a color, you can pick it with your mouse or write its HTML name/code it in its text box.\n",
"\n",
"We can see and set what color is selected using the field `StringValue`."
]
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 15,
"id": "8546ec77-be19-44f3-987e-91eafd890a5a",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "6564fe33-83bb-4230-b5b5-74704c9ec25a",
"model_id": "79b44a92-0e84-4efb-9b37-60fb8e7cb579",
"version_major": 2,
"version_minor": 0
}
@ -126,18 +145,86 @@
}
],
"source": [
"-- Creating a color widget\n",
"colorPicker <- mkColorPicker\n",
"setField colorPicker StringValue \"#fabada\"\n",
"colorPicker"
]
},
{
"cell_type": "markdown",
"id": "handled-barcelona",
"metadata": {},
"source": [
"We can display a condensed color picker, without the text box, setting `Concise` to `True`."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "19429010-1c60-4001-b69e-1db09f0066c4",
"execution_count": 16,
"id": "phantom-cricket",
"metadata": {},
"outputs": [],
"source": [
"setField colorPicker StringValue \"aquamarine\""
"setField colorPicker Concise True"
]
},
{
"cell_type": "markdown",
"id": "technical-forward",
"metadata": {},
"source": [
"Let's make a button that changes color to a color chosen by the user!"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "continent-given",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "79b44a92-0e84-4efb-9b37-60fb8e7cb579",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "005e2395-679b-4311-90bb-f793e92b2769",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- Creating the button and style\n",
"b <- mkButton\n",
"stl <- mkButtonStyle\n",
"setField b Style $ StyleWidget stl\n",
"\n",
"-- Creating the handler\n",
"colorHandler :: IO ()\n",
"colorHandler = getField colorPicker StringValue >>= setField stl ButtonColor . Just . unpack\n",
"-- calling the handler to initialize the button\n",
"colorHandler\n",
"\n",
"-- Setting color picker attributes\n",
"setField colorPicker Concise False\n",
"setField colorPicker ChangeHandler colorHandler\n",
"\n",
"-- Displaying the widgets\n",
"colorPicker\n",
"b"
]
},
{
@ -145,25 +232,37 @@
"id": "63bd4861-8db4-4782-a74f-dfc67183ae02",
"metadata": {},
"source": [
"### The `DatePicker` widget"
"### The `DatePicker` widget\n",
"\n",
"The Date Picker displays a calendar and allows you to display a date. It uses the data type `Date`. The first number is the year, then the month, then the day."
]
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 24,
"id": "fe024e0b-7b08-4fc9-ba22-1e706d31b4b8",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "2690ca3f-218f-479b-87df-eb1d88c69729",
"model_id": "29a2ae24-caf1-44a0-8275-b60fb4607134",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
@ -172,25 +271,23 @@
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "e48d68a2-d49e-45f2-89c4-cc8f8613187c",
"cell_type": "markdown",
"id": "caroline-aberdeen",
"metadata": {},
"outputs": [],
"source": [
"setField datePicker DateValue (Date 1999 15 30)"
"We can get the selected date getting the `DateValue` field. And we can extract the year, month and day using pattern matching. Be careful, as the date can also be `NullDate`, the following cell could fail if you didn't select a date value."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "5789b89d-f0d9-47b8-888f-54d30f4b2a27",
"execution_count": 32,
"id": "purple-specification",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1999-04-30"
"Today's date is 19/8/2021"
]
},
"metadata": {},
@ -198,7 +295,26 @@
}
],
"source": [
"getField datePicker DateValue"
"(Date y m d) <- getField datePicker DateValue\n",
"printf \"Today's date is %d/%d/%d\" d m y"
]
},
{
"cell_type": "markdown",
"id": "flexible-democracy",
"metadata": {},
"source": [
"If we set the Date to `NullDate`, then the widget appears empty"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "5789b89d-f0d9-47b8-888f-54d30f4b2a27",
"metadata": {},
"outputs": [],
"source": [
"setField datePicker DateValue NullDate"
]
}
],

View File

@ -6,18 +6,111 @@
"source": [
"## A complete plotting example\n",
"\n",
"This example is inspired from the [plot-gtk-ui](https://github.com/sumitsahrawat/plot-gtk-ui) package. Our goal will be to create an interface similar to the screenshot below.\n",
"\n",
"![Screenshot](https://raw.githubusercontent.com/sumitsahrawat/plot-gtk-ui/master/screenshots/sinax.png)"
"This example is inspired from the [plot-gtk-ui](https://github.com/sumitsahrawat/plot-gtk-ui) package. Our goal will be to create an interface to display functions."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"execution_count": 1,
"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><div class=\"suggestion-name\" style=\"clear:both;\">Unused LANGUAGE pragma</div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Found:</div><div class=\"highlight-code\" id=\"haskell\">{-# LANGUAGE OverloadedStrings #-}</div></div><div class=\"suggestion-row\" style=\"float: left;\"><div class=\"suggestion-warning\">Why Not:</div><div class=\"highlight-code\" id=\"haskell\"></div></div>"
],
"text/plain": [
"Line 1: Unused LANGUAGE pragma\n",
"Found:\n",
"{-# LANGUAGE OverloadedStrings #-}\n",
"Why not:"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"{-# LANGUAGE OverloadedStrings #-}\n",
"{-# LANGUAGE FlexibleContexts #-}\n",
@ -33,10 +126,8 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import Data.IORef\n",
@ -84,10 +175,8 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"import Data.IORef\n",
@ -97,7 +186,7 @@
"import IHaskell.Display (base64)\n",
"import Control.Applicative ((<$>))\n",
"\n",
"tempImgWidget <- mkImageWidget\n",
"tempImgWidget <- mkImage\n",
"\n",
"setField tempImgWidget Width 400\n",
"setField tempImgWidget Height 400\n",
@ -109,7 +198,7 @@
"update modifier = readIORef plotState >>= modifier >>= writeIORef plotState >> redraw\n",
"\n",
"redraw :: IO ()\n",
"redraw = readIORef plotState >>= mkPlot >>= setField tempImgWidget B64Value . base64\n",
"redraw = readIORef plotState >>= mkPlot >>= setField tempImgWidget BSValue . JSONByteString\n",
"\n",
"mkDset :: PlotInfo -> [(String, [(Double, Double)])]\n",
"mkDset info = let funcs = M.toList $ functions info\n",
@ -157,24 +246,26 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"divBox <- mkFlexBox\n",
"setField divBox Orientation HorizontalOrientation\n",
"divBox <- mkHBox\n",
"\n",
"-- Two parts: A FlexBox for the left part (plot + sliders) and an Accordion for the input elements.\n",
"plBox <- mkFlexBox\n",
"plBox <- mkVBox\n",
"tlBox <- mkAccordion\n",
"\n",
"-- Add the widgets to the main dividing box.\n",
"setField divBox Children [ChildWidget plBox, ChildWidget tlBox]\n",
"\n",
"-- Make the orientation Vertical\n",
"setField plBox Orientation VerticalOrientation"
"setField divBox Children [ChildWidget plBox, ChildWidget tlBox]"
]
},
{
@ -183,27 +274,29 @@
"source": [
"Now we fill in the plotting area with:\n",
"\n",
"+ A `FlexBox` to hold the sliders.\n",
"+ An `ImageWidget` to hold the plot."
"+ A `Box` to hold the sliders.\n",
"+ An `Image` Widget to hold the plot."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [],
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"slBox <- mkFlexBox\n",
"slBox <- mkVBox\n",
"\n",
"-- Reusing the image widget created before\n",
"let plImg = tempImgWidget\n",
"\n",
"-- Sliders need to be laid out vertically.\n",
"setField slBox Orientation VerticalOrientation\n",
"\n",
"-- Add widgets to the plotting region.\n",
"setField plBox Children [ChildWidget slBox, ChildWidget plImg]"
]
@ -214,18 +307,24 @@
"source": [
"Now, we fill the other half with the following:\n",
"\n",
"+ Four `FlexBox` widgets (title, sub-title, x-label, y-label), containing a `TextWidget` for title and a `BoundedFloatText` for the font size.\n",
"+ Four `Box` widgets (title, sub-title, x-label, y-label), containing a `Text` widget for title and a `BoundedFloatText` for the font size.\n",
"+ A `FlexBox` with two selection widgets for toggling visibility for different elements. We'll go with `ToggleButton` just for fun.\n",
"+ Two more `FlexBox`, with `FloatText` widgets for deciding the plot range."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- The four FlexBox widgets.\n",
"import Control.Monad (replicateM, forM_)\n",
@ -236,8 +335,8 @@
"-- pl : plotTitle\n",
"-- x : xLabel\n",
"-- y : yLabel\n",
"boxes <- replicateM 3 mkFlexBox\n",
"texts@[plTxt,xTxt,yTxt] <- replicateM 3 mkTextWidget\n",
"boxes <- replicateM 3 mkHBox\n",
"texts@[plTxt,xTxt,yTxt] <- replicateM 3 mkText\n",
"inpts@[plInp,xInp,yInp] <- replicateM 3 mkBoundedFloatText\n",
"\n",
"-- Adding event handlers for text widgets. This is a clumsy way to emulate first-class record fields.\n",
@ -261,7 +360,6 @@
"let boxInfo = zip4 boxes texts inpts [\"plot title\", \"X-Label\", \"Y-Label\"]\n",
"\n",
"forM_ boxInfo $ \\(box,text,input,placeholder) -> do\n",
" setField box Orientation HorizontalOrientation\n",
" setField box Children [ChildWidget text, ChildWidget input]\n",
" setField text Placeholder $ pack $ printf \"Enter %s here ...\" placeholder\n",
" setField input MinFloat 1\n",
@ -271,15 +369,20 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- A FlexBox with ToggleButtons\n",
"buttonBox <- mkFlexBox\n",
"setField buttonBox Orientation HorizontalOrientation\n",
"buttonBox <- mkHBox\n",
"tButtons@[xGrid,yGrid] <- replicateM 2 mkToggleButton\n",
"\n",
"let tgButtonInfo = zip tButtons [\"X-Grid\", \"Y-Grid\"]\n",
@ -300,22 +403,27 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import Control.Arrow (first, second)\n",
"\n",
"-- Finally, the ranges\n",
"rangeBoxes <- replicateM 2 mkFlexBox\n",
"rangeBoxes <- replicateM 2 mkHBox\n",
"fTxts@[xLow,xHigh,yLow,yHigh] <- replicateM 4 mkFloatText\n",
"\n",
"let rangeInfo = zip rangeBoxes [(xLow,xHigh), (yLow, yHigh)]\n",
"\n",
"forM_ rangeInfo $ \\(box, (lowTxt, highTxt)) -> do\n",
" setField box Orientation HorizontalOrientation\n",
" setField box Children (map ChildWidget [lowTxt, highTxt])\n",
"\n",
"let setHandler widget modifier = setField widget ChangeHandler $ update $ \\info -> do\n",
@ -337,11 +445,17 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"setField tlBox Children $ map ChildWidget $ boxes ++ [buttonBox] ++ rangeBoxes"
]
@ -355,10 +469,8 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"setField tlBox Titles [\"Plot title\", \"X-Label\", \"Y-Label\", \"Grid\", \"X-range\", \"Y-range\"]"
@ -373,11 +485,17 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"let syncVal widget value fieldGetter = readIORef plotState >>= setField widget value . fieldGetter\n",
" in do\n",
@ -407,10 +525,8 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"addFunction :: String -> (Double -> Double) -> IO ()\n",
@ -429,11 +545,226 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e094c747-9265-41f1-8c61-4f06b6316d0f",
"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"
}
],
"source": [
"-- Spurious update to display empty plot instead of empty image initially\n",
"update return\n",
@ -450,10 +781,8 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"addFunction \"sin\" sin"
@ -461,10 +790,8 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"addFunction \"cos\" cos"
@ -472,14 +799,19 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"addFunction \"x^2\" (\\x -> x * x)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
@ -491,10 +823,12 @@
"language_info": {
"codemirror_mode": "ihaskell",
"file_extension": ".hs",
"mimetype": "text/x-haskell",
"name": "haskell",
"version": "7.10.2"
"pygments_lexer": "Haskell",
"version": "8.10.4"
}
},
"nbformat": 4,
"nbformat_minor": 0
"nbformat_minor": 4
}

View File

@ -162,18 +162,18 @@
"source": [
"### Single Selection Widgets\n",
"\n",
"We can set the options with `Options $ OptionLabels [array]`. Let's see how can we select one of two functions with multiple selectors:"
"We can set the options setting the `OptionsLabels` field, which is an array of Text. Let's see how can we select one of two functions with multiple selectors:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "79ef5a0e-de6e-4374-8bad-4948deaffb05",
"model_id": "cc3cb3ef-76c6-45d4-8d94-c9f904128b63",
"version_major": 2,
"version_minor": 0
}
@ -184,7 +184,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "bb697874-4d8c-4841-af02-0ef2984df7b1",
"model_id": "a217e3a5-6b3a-4195-93f3-3e47a59e7780",
"version_major": 2,
"version_minor": 0
}
@ -195,7 +195,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "279a451a-6528-47b7-aca3-07d42be0e57b",
"model_id": "b7e86ecf-da03-4550-9ea9-98649e31b3d3",
"version_major": 2,
"version_minor": 0
}
@ -206,7 +206,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "72511b23-5bb3-4e25-85d7-ba0bae5f8a0d",
"model_id": "9b3a0173-3f8f-4023-97f4-347dd6665f3a",
"version_major": 2,
"version_minor": 0
}
@ -217,7 +217,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "131ab0e7-51c9-41ce-bc7c-7f31de28c38b",
"model_id": "f4e42990-e405-47c1-97f0-0f8de2eb8cd9",
"version_major": 2,
"version_minor": 0
}
@ -239,7 +239,7 @@
"source": [
"init w = do\n",
" setField w Description \"Function:\"\n",
" setField w Options (OptionLabels [\"sin\", \"cos\"])\n",
" setField w OptionsLabels [\"sin\", \"cos\"]\n",
" return w\n",
" \n",
"init tgbs\n",
@ -258,9 +258,17 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 9,
"metadata": {},
"outputs": [],
"outputs": [
{
"data": {
"text/plain": []
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"setHandlerOpt w = setField w SelectionHandler $ do\n",
" y <- getField w OptionalIndex\n",
@ -293,6 +301,8 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, if you click in any of the widgets, the value on all the other widgets should change too.\n",
"\n",
"### Multiple Selection Widgets\n",
"\n",
"In the multiple selection widget, you can select multiple items by doing Shift+Click. Let's do an example for selecting provinces (maybe for filtering later)."
@ -300,13 +310,13 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "615fb6a1-85b1-4cfc-9621-3f7f74ac46a3",
"model_id": "f687e5f8-3df0-4e27-aad2-42e439a32491",
"version_major": 2,
"version_minor": 0
}
@ -316,13 +326,14 @@
}
],
"source": [
"msel <- mkSelectMultiple\n",
"ccaa = \n",
" [ \"Andalusia\", \"Aragon\", \"Asturias\", \"Balearic Islands\", \"Basque Country\"\n",
" , \"Canary Islands\", \"Cantabria\", \"Castile and León\", \"Castilla-La Mancha\", \"Catalonia\"\n",
" , \"Madrid\", \"Extremadura\", \"Galicia\", \"La Rioja\", \"Navarre\", \"Murcia\", \"Valencia\"\n",
" ]\n",
" \n",
"setField msel Options (OptionLabels ccaa)\n",
"setField msel OptionsLabels ccaa\n",
"msel"
]
},
@ -335,24 +346,23 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"setField msel Indices [0,2]\n",
"setField msel Indices [-1,3]"
"setField msel Indices [0,2]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"But maybe we to scroll a lot because we don't have enough space, which is a bit tiring. We can fix this setting the `Rows` attribute. If we set it to `Nothing`, we are letting the frontend decide the number of rows."
"But we have to scroll a lot because we don't have enough space, which is a bit tiring. To fix this we can set a bigger number in the `Rows` attribute. This attribute tells the frontend how many rows we want to display. If we set it to `Nothing`, we are letting the frontend decide the number of rows."
]
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
@ -368,13 +378,13 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "35e31cd5-834c-4357-9926-bad42f4a0f88",
"model_id": "ef3f3191-b86b-4ad8-be4f-b824b9e15786",
"version_major": 2,
"version_minor": 0
}
@ -397,96 +407,6 @@
"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": {},
@ -494,7 +414,7 @@
}
],
"source": [
"setField rslider Options (OptionLabels [\"Very bad\", \"Bad\", \"Regular\", \"Good\", \"Very good\"])\n",
"setField rslider OptionsLabels [\"Very bad\", \"Bad\", \"Regular\", \"Good\", \"Very good\"]\n",
"rslider"
]
},
@ -507,13 +427,13 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[2,4]"
"[1,3]"
]
},
"metadata": {},
@ -524,13 +444,6 @@
"getField rslider Indices\n",
"setField rslider Indices [1,3]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {

View File

@ -6,9 +6,11 @@
"source": [
"## The String Widgets\n",
"\n",
"+ HTMLWidget\n",
"+ LatexWidget\n",
"+ TextWidget\n",
"+ HTML\n",
"+ HTMLMath\n",
"+ Label\n",
"+ Password\n",
"+ Text\n",
"+ TextArea"
]
},
@ -131,9 +133,8 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 18,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
@ -141,9 +142,11 @@
"outputs": [],
"source": [
"-- Constructors\n",
"html <- mkHTMLMathWidget\n",
"text <- mkTextWidget\n",
"area <- mkTextArea"
"html <- mkHTML\n",
"htmlMath <- mkHTMLMath\n",
"text <- mkText\n",
"area <- mkTextArea\n",
"pass <- mkPassword"
]
},
{
@ -164,12 +167,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The `HTMLWidget` displays `Text` as rich formatted *HTML* and *LaTeX* respectively."
"The `HTML` widget displays `Text` as rich formatted *HTML*, but the `HTMLMath` widget can display *LaTeX* as well."
]
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 10,
"metadata": {
"tags": []
},
@ -177,7 +180,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e500c08b-1f22-4759-b49a-03c69b363f3c",
"model_id": "7d9bbee6-5fc5-4790-b5ae-500d1966750f",
"version_major": 2,
"version_minor": 0
}
@ -193,9 +196,8 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 12,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
@ -203,87 +205,13 @@
"outputs": [],
"source": [
"-- Set some html string\n",
"setField html StringValue \"$$\\\\sum_{i=0}^{i < n} i =\\\\frac{n\\\\cdot(n+1)}{2}$$\""
"setField html StringValue \"<b>Hello</b> <i>World!</i>\""
]
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 13,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"ename": "",
"evalue": "",
"header": "MessageHeader {mhIdentifiers = [\"cc9f9fee-d501-4dfc-a090-4027036b4613\"], mhParentHeader = Just (MessageHeader {mhIdentifiers = [\"cc9f9fee-d501-4dfc-a090-4027036b4613\"], mhParentHeader = Nothing, mhMetadata = Metadata (fromList [(\"jupyter\",Object (fromList [(\"outputs_hidden\",Bool False)])),(\"recordTiming\",Bool False),(\"deletedCells\",Array []),(\"cellId\",String \"030c5cf0-234e-4150-98c3-ba7b04015ef4\"),(\"collapsed\",Bool False)]), mhMessageId = UUID {uuidToString = \"e2051452-137c-40e3-ab4a-6e3e54661a4d\"}, mhSessionId = UUID {uuidToString = \"cc9f9fee-d501-4dfc-a090-4027036b4613\"}, mhUsername = \"\", mhMsgType = ExecuteRequestMessage, mhBuffers = []}), mhMetadata = Metadata (fromList []), mhMessageId = UUID {uuidToString = \"514c7c07-d388-4889-9ecf-57789924bd64\"}, mhSessionId = UUID {uuidToString = \"cc9f9fee-d501-4dfc-a090-4027036b4613\"}, mhUsername = \"\", mhMsgType = ExecuteErrorMessage, mhBuffers = []}",
"output_type": "error",
"traceback": [
"<interactive>:1:1: error:\n • No instance for (Data.Vinyl.Lens.RecElem\n Data.Vinyl.Core.Rec\n 'ihaskell-widgets-0.3.0.0:IHaskell.Display.Widgets.Singletons.Width\n 'ihaskell-widgets-0.3.0.0:IHaskell.Display.Widgets.Singletons.Width\n '[]\n '[]\n (Data.Vinyl.TypeLevel.RIndex 'ihaskell-widgets-0.3.0.0:IHaskell.Display.Widgets.Singletons.Width '[]))\n arising from a use of setField\n • In the expression: setField html Width 400\n In an equation for it: it = setField html Width 400"
]
}
],
"source": [
"-- Set some latex string\n",
"setField html StringValue \"$x + y$\"\n",
"\n",
"-- The default width of LatexWidget is somewhat small\n",
"setField html Width 400"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also add some padding to the widgets."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"ename": "",
"evalue": "",
"header": "MessageHeader {mhIdentifiers = [\"cc9f9fee-d501-4dfc-a090-4027036b4613\"], mhParentHeader = Just (MessageHeader {mhIdentifiers = [\"cc9f9fee-d501-4dfc-a090-4027036b4613\"], mhParentHeader = Nothing, mhMetadata = Metadata (fromList [(\"jupyter\",Object (fromList [(\"outputs_hidden\",Bool False)])),(\"recordTiming\",Bool False),(\"deletedCells\",Array []),(\"cellId\",String \"60b8eea0-31b0-48da-9704-b67836923cc9\"),(\"collapsed\",Bool False)]), mhMessageId = UUID {uuidToString = \"bca761f2-d99e-42ca-8e25-917642cc3afb\"}, mhSessionId = UUID {uuidToString = \"cc9f9fee-d501-4dfc-a090-4027036b4613\"}, mhUsername = \"\", mhMsgType = ExecuteRequestMessage, mhBuffers = []}), mhMetadata = Metadata (fromList []), mhMessageId = UUID {uuidToString = \"49b9b28f-28cb-4b29-80e5-cdd3bbf3316c\"}, mhSessionId = UUID {uuidToString = \"cc9f9fee-d501-4dfc-a090-4027036b4613\"}, mhUsername = \"\", mhMsgType = ExecuteErrorMessage, mhBuffers = []}",
"output_type": "error",
"traceback": [
"<interactive>:1:15: error: Data constructor not in scope: Padding :: ihaskell-widgets-0.3.0.0:IHaskell.Display.Widgets.Singletons.SField f0"
]
}
],
"source": [
"setField html Padding 50"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `TextWidget` and `TextArea`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, let's see what they look like:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
@ -292,7 +220,48 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "5c49562f-2e86-43c4-a686-ccb02f57e582",
"model_id": "7503927b-868d-42d3-b523-80b1beb891cd",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"-- Set some latex string\n",
"setField htmlMath StringValue \"$$\\\\sum_{i=0}^{i < n} i =\\\\frac{n\\\\cdot(n+1)}{2}$$\"\n",
"htmlMath"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### `TextWidget`, `Password` & `TextArea`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"These widgets allow you to obtain text input. First, let's see what they look like:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "93ea02c6-5afc-4e10-813e-3a7d019e4688",
"version_major": 2,
"version_minor": 0
}
@ -303,57 +272,77 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "5f9cf0e5-3d78-4cfa-b62a-eef279d37af2",
"model_id": "f06f4e78-7ad0-4309-b094-7f797278ed1e",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "a5a7eea1-3090-4351-a021-65618ddaa5a5",
"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": [
"text\n",
"pass\n",
"area"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
},
"outputs": [
{
"ename": "",
"evalue": "",
"header": "MessageHeader {mhIdentifiers = [\"cc9f9fee-d501-4dfc-a090-4027036b4613\"], mhParentHeader = Just (MessageHeader {mhIdentifiers = [\"cc9f9fee-d501-4dfc-a090-4027036b4613\"], mhParentHeader = Nothing, mhMetadata = Metadata (fromList [(\"jupyter\",Object (fromList [(\"outputs_hidden\",Bool False)])),(\"recordTiming\",Bool False),(\"deletedCells\",Array []),(\"cellId\",String \"bdeaa7cb-c083-4b81-88df-8cc5d0d299e8\"),(\"collapsed\",Bool False)]), mhMessageId = UUID {uuidToString = \"d46a7f8c-f418-46b1-8a20-1a522398a714\"}, mhSessionId = UUID {uuidToString = \"cc9f9fee-d501-4dfc-a090-4027036b4613\"}, mhUsername = \"\", mhMsgType = ExecuteRequestMessage, mhBuffers = []}), mhMetadata = Metadata (fromList []), mhMessageId = UUID {uuidToString = \"f42ca945-c678-4cfb-bcbb-80f87eb5b6cb\"}, mhSessionId = UUID {uuidToString = \"cc9f9fee-d501-4dfc-a090-4027036b4613\"}, mhUsername = \"\", mhMsgType = ExecuteErrorMessage, mhBuffers = []}",
"output_type": "error",
"traceback": [
"<interactive>:1:15: error: Data constructor not in scope: Padding :: ihaskell-widgets-0.3.0.0:IHaskell.Display.Widgets.Singletons.SField f0"
]
}
],
"source": [
"-- Some padding\n",
"setField text Padding 5"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The `TextWidget` and `TextArea` also have a `Placeholder` property, which represents the text displayed in empty widgets."
"The first one has been created to input a word, but the second one is bigger and resizeable, making it better to big text input. The `TextWidget` and `TextArea` also have a `Placeholder` property, which represents the text displayed when the user has not made any input yet.\n",
"\n",
"> **NOTE ABOUT PASSWORD WIDGET**: This widget **is not** a **secure** way to collect sensitive information.\n",
"> - The contents of the `Password` widget are transmitted unencrypted between the frontend and the kernel\n",
"> - If you save the notebook, the contents of the widget are stored as plaintext"
]
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 25,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
@ -361,12 +350,13 @@
"outputs": [],
"source": [
"setField text Placeholder \"Enter your text here...\"\n",
"setField pass Placeholder \"Password\"\n",
"setField area Placeholder \"Parsed output will appear here...\""
]
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 27,
"metadata": {},
"outputs": [
{
@ -378,6 +368,15 @@
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"\"agsagsa\""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
@ -390,6 +389,7 @@
],
"source": [
"getField text StringValue\n",
"getField pass StringValue\n",
"getField area StringValue"
]
},
@ -397,7 +397,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Both the widgets also accept input. The `StringValue` of the widget is automatically updated on every change to the widget. Additionally, the `TextWidget` also has a `SubmitHandler` which is triggered on hitting the return/enter key."
"The widgets also accept input. The `StringValue` of the widget is automatically updated on every change to the widget. Additionally, the `TextWidget` also has a `SubmitHandler` which is triggered on hitting the return/enter key."
]
},
{
@ -409,7 +409,7 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": 28,
"metadata": {
"tags": []
},
@ -432,7 +432,7 @@
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": 29,
"metadata": {
"tags": []
},
@ -493,9 +493,8 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 30,
"metadata": {
"collapsed": false,
"jupyter": {
"outputs_hidden": false
}
@ -529,12 +528,12 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We can re-display the widgets (nobody likes to scroll needlessly):"
"We can re-display the widgets (nobody likes to scroll needlessly). Now you can input a telephone number on the text widget, and it should be parsed and displayed to the text area."
]
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 31,
"metadata": {
"tags": []
},
@ -542,7 +541,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "5c49562f-2e86-43c4-a686-ccb02f57e582",
"model_id": "93ea02c6-5afc-4e10-813e-3a7d019e4688",
"version_major": 2,
"version_minor": 0
}
@ -553,13 +552,208 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "5f9cf0e5-3d78-4cfa-b62a-eef279d37af2",
"model_id": "a5a7eea1-3090-4351-a021-65618ddaa5a5",
"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"
}
],
"source": [
@ -571,79 +765,127 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### The `Password` widget"
"### The `Password` widget\n",
"\n",
"It works the same as the `Text` widget, but it hides the text from the user. Can you guess the password and make the valid widget green?"
]
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": 36,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "cc816c64-617e-4d83-9a23-2232048558b8",
"model_id": "6db784a4-191f-4087-bb9a-0a2932eae40e",
"version_major": 2,
"version_minor": 0
}
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"pwd <- mkPasswordWidget\n",
"pwd"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"\"ewaasfagasga\""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"getField pwd StringValue\n",
"setField pwd StringValue \"1234\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### The `Combobox` widget"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "8a51c2fc-065f-4862-b5fa-38844f39ff3b",
"model_id": "6c243e81-e59c-453c-98a0-b394c43b4a93",
"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"
}
],
"source": [
"combo <- mkComboboxWidget\n",
"setField combo Options [\"Hola\", \"Prueba1\", \"Prueba2\"]\n",
"combo"
"valid <- mkValid\n",
"pwd <- mkPassword\n",
"\n",
"setField pwd ChangeHandler $ getField pwd StringValue >>= setField valid BoolValue . (\"1234\"==)\n",
"\n",
"pwd\n",
"valid"
]
}
],

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@ name: ihaskell-widgets
-- PVP summary: +-+------- breaking API changes
-- | | +----- non-breaking API additions
-- | | | +--- code changes with no API change
version: 0.3.0.0
version: 0.3.1.0
-- A short (one-line) description of the package.
synopsis: IPython standard widgets for IHaskell.

View File

@ -77,4 +77,4 @@ import IHaskell.Display.Widgets.Common as X
import IHaskell.Display.Widgets.Types as X (setField, getField, properties, triggerDisplay,
triggerChange, triggerClick, triggerSelection,
triggerSubmit, ChildWidget(..), StyleWidget(..),
WidgetFieldPair(..), Date(..), unlink)
WidgetFieldPair(..), Date(..), unlink, JSONByteString(..))

View File

@ -43,6 +43,7 @@ mkColorPicker = do
color = (StringValue =:: "black")
:& (Concise =:: False)
:& (Disabled =:: False)
:& (ChangeHandler =:: return ())
:& RNil
colorPickerState = WidgetState (ddw <+> color)
@ -58,3 +59,9 @@ mkColorPicker = do
instance IHaskellWidget ColorPicker where
getCommUUID = uuid
comm widget val _ =
case nestedObjectLookup val ["state", "value"] of
Just o -> case fromJSON o of
Success (String color) -> setField' widget StringValue color >> triggerChange widget
_ -> pure ()
_ -> pure ()

View File

@ -15,8 +15,6 @@ module IHaskell.Display.Widgets.DatePicker
-- To keep `cabal repl` happy when running from the ihaskell repo
import Prelude
import Control.Monad (void)
import Data.Aeson
import Data.IORef (newIORef)
import Data.Vinyl (Rec(..), (<+>))
@ -44,6 +42,7 @@ mkDatePicker = do
let ddw = defaultDescriptionWidget "DatePickerView" "DatePickerModel" layout $ StyleWidget dstyle
date = (DateValue =:: defaultDate)
:& (Disabled =:: False)
:& (ChangeHandler =:: return ())
:& RNil
datePickerState = WidgetState (ddw <+> date)
@ -62,6 +61,6 @@ instance IHaskellWidget DatePicker where
comm widget val _ =
case nestedObjectLookup val ["state", "value"] of
Just o -> case fromJSON o of
Success date -> void $ setField' widget DateValue date
Success date -> setField' widget DateValue date >> triggerChange widget
_ -> pure ()
_ -> pure ()

View File

@ -374,10 +374,10 @@ type instance WidgetFields 'ButtonType =
['S.Disabled, 'S.Icon, 'S.ButtonStyle,'S.ClickHandler]
type instance WidgetFields 'ColorPickerType =
DescriptionWidgetClass :++
['S.StringValue, 'S.Concise, 'S.Disabled]
['S.StringValue, 'S.Concise, 'S.Disabled, 'S.ChangeHandler]
type instance WidgetFields 'DatePickerType =
DescriptionWidgetClass :++
['S.DateValue, 'S.Disabled]
['S.DateValue, 'S.Disabled, 'S.ChangeHandler]
type instance WidgetFields 'AudioType =
MediaClass :++ ['S.AudioFormat, 'S.AutoPlay, 'S.Loop, 'S.Controls]