mirror of
https://github.com/IHaskell/IHaskell.git
synced 2025-04-18 20:36:08 +00:00
Selection widget demo
This commit is contained in:
parent
d26ecb0209
commit
5a03d3ddd5
@ -10,138 +10,527 @@
|
||||
"+ RadioButtons\n",
|
||||
"+ ToggleButtons\n",
|
||||
"+ Select\n",
|
||||
"+ SelectMultiple"
|
||||
"+ SelectMultiple\n",
|
||||
"+ SelectionSlider\n",
|
||||
"+ SelectionRangeSlider"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"These widgets can be used to choose between multiple alternatives. The `SelectMultiple` widget allows multiple selections, whereas `Dropdown`, `RadioButtons`, `ToggleButtons`, and `Select` only allow one selection."
|
||||
"These widgets can be used to choose between multiple alternatives. The `SelectMultiple` widget allows multiple selections, whereas `Dropdown`, `RadioButtons`, `ToggleButtons`, `SelectionSlider` and `Select` only allow one selection. `SelectionRangeSlider` returns exactly two selections.\n",
|
||||
"\n",
|
||||
"Every widget, except the sliders, can return `Nothing` as it selected index."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
"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",
|
||||
"import IHaskell.Display.Widgets"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
"jupyter": {
|
||||
"outputs_hidden": false
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"-- Allows single selection\n",
|
||||
"tgbs <- mkToggleButtons\n",
|
||||
"dropdown <- mkDropdown\n",
|
||||
"radio <- mkRadioButtons\n",
|
||||
"select <- mkSelect\n",
|
||||
"slider <- mkSelectionSlider\n",
|
||||
"\n",
|
||||
"-- Allows multiple selections\n",
|
||||
"msel <- mkSelectMultiple"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"setField msel Description \"Functions to show (One or more)\"\n",
|
||||
"setField msel Options (OptionLabels [\"sin\", \"cos\"])\n",
|
||||
"\n",
|
||||
"setField tgbs Description \"Plot style\"\n",
|
||||
"setField tgbs Options (OptionLabels [\"line\", \"point\"])"
|
||||
"msel <- mkSelectMultiple\n",
|
||||
"rslider <- mkSelectionRangeSlider"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The cell below requires `Chart` and `Chart-cairo` to be installed."
|
||||
"### 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:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false,
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [],
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "79ef5a0e-de6e-4374-8bad-4948deaffb05",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
}
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "bb697874-4d8c-4841-af02-0ef2984df7b1",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
}
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "279a451a-6528-47b7-aca3-07d42be0e57b",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
}
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "72511b23-5bb3-4e25-85d7-ba0bae5f8a0d",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
}
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "131ab0e7-51c9-41ce-bc7c-7f31de28c38b",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
}
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
},
|
||||
{
|
||||
"data": {},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import Graphics.Rendering.Chart.Easy hiding (tan)\n",
|
||||
"import Graphics.Rendering.Chart.Backend.Cairo\n",
|
||||
"import qualified Data.ByteString as B\n",
|
||||
"import Data.Text (pack, unpack)\n",
|
||||
"import IHaskell.Display (base64)\n",
|
||||
"import Control.Applicative ((<$>))\n",
|
||||
"\n",
|
||||
"import Control.Monad (when, forM)\n",
|
||||
"import Data.Maybe (fromJust)\n",
|
||||
"\n",
|
||||
"dset :: [(String, [(Double, Double)])]\n",
|
||||
"dset = [(\"sin\", zmap sin r), (\"cos\", zmap cos r)]\n",
|
||||
" where zmap f xs = zip xs (map f xs)\n",
|
||||
" r = [0, 0.1 .. 6.3]\n",
|
||||
"\n",
|
||||
"i <- mkImageWidget\n",
|
||||
"setField i Width 500\n",
|
||||
"setField i Height 500\n",
|
||||
"\n",
|
||||
"-- Redraw the plot based on values from the widgets\n",
|
||||
"refresh = do\n",
|
||||
" -- Read values from the widgets\n",
|
||||
" funs <- map unpack <$> getField msel SelectedValues\n",
|
||||
" sty <- unpack <$> getField tgbs SelectedValue\n",
|
||||
" \n",
|
||||
" let pts = zip funs (map (fromJust . flip lookup dset) funs)\n",
|
||||
" opts = def { _fo_size = (500, 500) }\n",
|
||||
" toFile opts \".chart\" $ do\n",
|
||||
" layout_title .= \"Plotting: \" ++ unwords funs\n",
|
||||
" if sty == \"line\"\n",
|
||||
" then mapM_ (\\(s, ps) -> plot (line s [ps])) pts\n",
|
||||
" else mapM_ (\\(s, ps) -> plot (points s ps)) pts\n",
|
||||
"\n",
|
||||
" img <- B.readFile \".chart\"\n",
|
||||
" setField i B64Value (base64 img)\n",
|
||||
" \n",
|
||||
"-- Add event handlers to make widgets work\n",
|
||||
"setField msel SelectionHandler refresh\n",
|
||||
"setField tgbs SelectionHandler refresh\n",
|
||||
"\n",
|
||||
"-- Trigger event to show empty grid initially\n",
|
||||
"triggerSelection msel"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"-- Display the widgets\n",
|
||||
"msel\n",
|
||||
"tgbs\n",
|
||||
"i"
|
||||
"init w = do\n",
|
||||
" setField w Description \"Function:\"\n",
|
||||
" setField w Options (OptionLabels [\"sin\", \"cos\"])\n",
|
||||
" return w\n",
|
||||
" \n",
|
||||
"init tgbs\n",
|
||||
"init dropdown\n",
|
||||
"init radio\n",
|
||||
"init select\n",
|
||||
"init slider"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The `Dropdown`, `RadioButtons` and `Select` widgets behave just like the `ToggleButtons` widget. They have the same properties, and the same functionality."
|
||||
"We can create a `SelectionHandler` function that will be run every time the value is changed. Let's synchronize them so all the selectors always display the same value."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"setHandlerOpt w = setField w SelectionHandler $ do\n",
|
||||
" y <- getField w OptionalIndex\n",
|
||||
" case y of\n",
|
||||
" Just x -> do\n",
|
||||
" setField dropdown OptionalIndex $ Just x\n",
|
||||
" setField tgbs OptionalIndex $ Just x\n",
|
||||
" setField radio OptionalIndex $ Just x\n",
|
||||
" setField select OptionalIndex $ Just x\n",
|
||||
" setField slider Index x\n",
|
||||
" _ -> return ()\n",
|
||||
" \n",
|
||||
"setHandler w = setField w SelectionHandler $ do\n",
|
||||
" x <- getField w Index\n",
|
||||
" setField dropdown OptionalIndex $ Just x\n",
|
||||
" setField tgbs OptionalIndex $ Just x\n",
|
||||
" setField radio OptionalIndex $ Just x\n",
|
||||
" setField select OptionalIndex $ Just x\n",
|
||||
" setField slider Index x\n",
|
||||
" \n",
|
||||
"\n",
|
||||
"setHandlerOpt tgbs\n",
|
||||
"setHandlerOpt dropdown\n",
|
||||
"setHandlerOpt radio\n",
|
||||
"setHandlerOpt select\n",
|
||||
"setHandler slider"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### 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)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "615fb6a1-85b1-4cfc-9621-3f7f74ac46a3",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
}
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"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",
|
||||
"msel"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We can also set the items selected with the `Indices` attribute (which is an Integer list)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"setField msel Indices [0,2]\n",
|
||||
"setField msel Indices [-1,3]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"setField msel Rows $ Just 10"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Now let's create a slider. This one also returns an array of `Indices`, but it's always of size 2."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "35e31cd5-834c-4357-9926-bad42f4a0f88",
|
||||
"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"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"setField rslider Options (OptionLabels [\"Very bad\", \"Bad\", \"Regular\", \"Good\", \"Very good\"])\n",
|
||||
"rslider"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"As expected, we can get/set the selected values."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[2,4]"
|
||||
]
|
||||
},
|
||||
"metadata": {},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"getField rslider Indices\n",
|
||||
"setField rslider Indices [1,3]"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
@ -153,10 +542,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
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ mkSelectionRangeSlider = do
|
||||
:& (ReadOut =:: True)
|
||||
:& (ContinuousUpdate =:: True)
|
||||
:& RNil
|
||||
widgetState = WidgetState $ rput (Indices =:: [0,0]) $ selectionAttrs <+> selectionRangeSliderAttrs
|
||||
widgetState = WidgetState $ rput (Indices =:. ([0,0], rangeSliderVerification)) $ selectionAttrs <+> selectionRangeSliderAttrs
|
||||
|
||||
stateIO <- newIORef widgetState
|
||||
|
||||
|
@ -128,7 +128,7 @@ type CoreWidgetClass = ['S.ViewModule, 'S.ViewModuleVersion, 'S.ModelModule, 'S.
|
||||
|
||||
type DOMWidgetClass = ['S.ModelName, 'S.ViewName, 'S.DOMClasses, 'S.Tabbable, 'S.Tooltip, 'S.DisplayHandler] -- TODO: Add layout
|
||||
|
||||
type DescriptionWidgetClass = CoreWidgetClass ++ DOMWidgetClass :++ '[ 'S.Description ]
|
||||
type DescriptionWidgetClass = CoreWidgetClass :++ DOMWidgetClass :++ '[ 'S.Description ]
|
||||
|
||||
type StringClass = DescriptionWidgetClass :++ ['S.StringValue, 'S.Placeholder]
|
||||
|
||||
@ -323,7 +323,7 @@ type family WidgetFields (w :: WidgetType) :: [Field] where
|
||||
WidgetFields 'SelectionRangeSliderType = MultipleSelectionClass :++ '[ 'S.Orientation, 'S.ReadOut, 'S.ContinuousUpdate ]
|
||||
WidgetFields 'ToggleButtonsType =
|
||||
SelectionClass :++ ['S.Tooltips, 'S.Icons, 'S.ButtonStyle]
|
||||
WidgetFields 'SelectMultipleType = MultipleSelectionClass ++ '[ S.Rows ]
|
||||
WidgetFields 'SelectMultipleType = MultipleSelectionClass :++ '[ 'S.Rows ]
|
||||
WidgetFields 'IntTextType = IntClass :++ [ 'S.Disabled, 'S.ContinuousUpdate, 'S.StepInt ]
|
||||
WidgetFields 'BoundedIntTextType = BoundedIntClass :++ [ 'S.Disabled, 'S.ContinuousUpdate, 'S.StepInt ]
|
||||
WidgetFields 'IntSliderType =
|
||||
@ -587,6 +587,10 @@ instance ToPairs (Attr 'S.Rows) where
|
||||
(=::) :: (SingI f, Typeable (FieldType f)) => Sing f -> FieldType f -> Attr f
|
||||
s =:: x = Attr { _value = Real x, _verify = return, _field = reflect s }
|
||||
|
||||
-- | Store the value for a field, with a custom verification
|
||||
(=:.) :: (SingI f, Typeable (FieldType f)) => Sing f -> (FieldType f, FieldType f -> IO (FieldType f) ) -> Attr f
|
||||
s =:. (x,v) = Attr { _value = Real x, _verify = v, _field = reflect s }
|
||||
|
||||
-- | If the number is in the range, return it. Otherwise raise the appropriate (over/under)flow
|
||||
-- exception.
|
||||
rangeCheck :: (Num a, Ord a) => (a, a) -> a -> IO a
|
||||
@ -596,6 +600,12 @@ rangeCheck (l, u) x
|
||||
| u < x = Ex.throw Ex.Overflow
|
||||
| otherwise = error "The impossible happened in IHaskell.Display.Widgets.Types.rangeCheck"
|
||||
|
||||
rangeSliderVerification :: [Integer] -> IO [Integer]
|
||||
rangeSliderVerification xs@[a,b]
|
||||
| a <= b = return xs
|
||||
| otherwise = Ex.throw $ Ex.AssertionFailed "The first index should be smaller than the second"
|
||||
rangeSliderVerification _ = Ex.throw $ Ex.AssertionFailed "There should be two indices"
|
||||
|
||||
-- | Store a numeric value, with verification mechanism for its range.
|
||||
ranged :: (SingI f, Num (FieldType f), Ord (FieldType f), Typeable (FieldType f))
|
||||
=> Sing f -> (FieldType f, FieldType f) -> AttrVal (FieldType f) -> Attr f
|
||||
|
Loading…
x
Reference in New Issue
Block a user