Commit 14781f81 authored by David Davó's avatar David Davó

Updated widgets sample Notebooks

parent 6dbb61ef
# 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
......
......@@ -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"
]
}
],
......
......@@ -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": {
......
......@@ -5,7 +5,10 @@
"id": "089cfc9a-ee04-4a75-b519-e1b1ef4c5ed5",
"metadata": {},
"source": [
"The layout widget is a widget that adheres to any other widget"
"# 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..."
]
},
{
......@@ -114,10 +117,18 @@
"source": [
"{-# LANGUAGE OverloadedStrings #-}\n",
"import IHaskell.Display.Widgets\n",
"import IHaskell.Display.Widgets.Layout\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,
......@@ -127,7 +138,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e3fec42f-c887-4ecf-922d-b4a3754cee5a",
"model_id": "7d321970-3eda-40b4-818f-f468e1942fff",
"version_major": 2,
"version_minor": 0
}
......@@ -142,6 +153,14 @@
"button"
]
},
{
"cell_type": "markdown",
"id": "supreme-ribbon",
"metadata": {},
"source": [
"Then, we get the associated Layout widget with `getField`"
]
},
{
"cell_type": "code",
"execution_count": 3,
......@@ -149,8 +168,15 @@
"metadata": {},
"outputs": [],
"source": [
"layout <- mkLayout\n",
"setField button Layout $ Just layout"
"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."
]
},
{
......@@ -216,14 +242,54 @@
},
{
"cell_type": "code",
"execution_count": 6,
"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": "e3fec42f-c887-4ecf-922d-b4a3754cee5a",
"model_id": "bfe255db-9a90-47da-9032-48440e0a0b18",
"version_major": 2,
"version_minor": 0
}
......@@ -233,18 +299,207 @@
}
],
"source": [
"setField layout Border $ Just \"3px solid red\"\n",
"button"
"-- 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": "141277e9-4082-4b93-a597-9f34c4bfcf2c",
"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 layout Visibility $ Just \"unset\""
"setField style HandleColor $ Just \"pink\""
]
}
],
......
......@@ -5,21 +5,15 @@
"metadata": {},
"source": [
"## The `Media` Widgets\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."
"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": "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",
......
......@@ -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"
]
}
],
......
......@@ -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"
]
}
],
......
......@@ -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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment