"**NOTE**: Only the `Int` widgets are shown in this notebook. The `Float` widgets are the same as their `Int` counterparts, but hold `Float`s instead of `Int`s."
"----------------------\n",
"\n",
"First of all, we have to import the Widgets library. Sometimes we need some Haskell language extensions. We need `OverloadedStrings` because some widget methods receive a `Text` as an argument, instead of a `[Char]`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"metadata": {},
"outputs": [],
"source": [
"{-# LANGUAGE OverloadedStrings #-}\n",
...
...
@@ -41,131 +41,315 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"#### `IntText` and `BoundedIntText`"
"#### `IntText` and `FloatText`\n",
"We are going to see how the `Text` family works. They create a \"Stepper\", which lets us click to increment a certain amount. We can also input the number as if it were text."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
"metadata": {},
"outputs": [],
"source": [
"intt <- mkIntText\n",
"floatt <- mkFloatText\n",
"intt\n",
"floatt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For any numeric widget, we can use `getField w IntValue` and `getField w FloatValue` to obtain the value stored in the widget. Try changing the numbers in the widgets and then executing the cell bellow!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"int <- mkIntText\n",
"int"
"getField intt IntValue\n",
"getField floatt FloatValue"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also use these results for any computation. For example, let us add them together:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
"metadata": {},
"outputs": [],
"source": [
"x <- getField intt IntValue\n",
"y <- getField floatt FloatValue\n",
"\n",
"(fromIntegral x) + y"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"But incrementing and decrementing one by one is a bit boring... We can change the number incremented each step if we set the `StepInt` and `StepFloat` fields."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"bit <- mkBoundedIntText\n",
"bit"
"setField intt StepInt 5\n",
"setField floatt StepFloat 0.5"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Both the widgets are similar, but the second one possesses some additional properties."
"Try clicking on the buttons of the text field now.\n",
"\n",
"By the way, does this mean that we can change other fields with `setField`? Yes! For example, let us change the `IntValue`/`FloatValue`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
"metadata": {},
"outputs": [],
"source": [
"setField intt IntValue 42\n",
"setField floatt FloatValue 3.14"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"One special field is the `ChangeHandler`. This field is an IO function that is executed everytime the value is changed. We are going to \"sync\" the two widgets using two `ChangeHandler` functions. Each time the value changes in one widget, it is changed on the other widget too."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"setField bit MaxInt 20\n",
"setField bit MinInt 10\n",
"setField bit ChangeHandler (getField bit IntValue >>= print)"
"-- Let's display the widgets again so we don't have to scroll up and down\n",
"intt\n",
"floatt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, the first widget will accept arbitrary input whereas the second one wil accept input in the the 10-20 range. For example, try entering large values and hitting return/enter in the second widget."
"#### `BoundedIntText` and `BoundedFloatText`\n",
"\n",
"So, what's the difference between the Bounded family and the other two? `Bounded` widgets have the `Max` and `Min` attributes, which let you set an upper and lower bound. Let's try it"
"If you try clicking on the buttons or editing the text, you can't but anything that is not between the `Min` and `Max`! That's pretty neat, but, if you want to do something with bounds, maybe it's better to use an slider"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Both these widgets are sliders (duh!). `IntSlider` represents a single value, whereas `IntRangeSlider` represents a pair (range) of values."
"#### `IntSlider`, `FloatSlider`, `FloatLogSlider`, `IntRangeSlider` and `FloatRangeSlider`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"All these widgets are sliders (duh!). `IntSlider`, `FloatSlider` and `FloatLogSlider` represent a single value, whereas `IntRangeSlider` and `FloatRangeSlider` represent a pair (range) of values. `FloatLogSlider` uses a logarithmic scale, which means that every step will multiply (instead of increment) the value!"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"metadata": {},
"outputs": [],
"source": [
"ins <- mkIntSlider\n",
"irs <- mkIntRangeSlider"
"irs <- mkIntRangeSlider\n",
"fns <- mkFloatSlider\n",
"fls <- mkFloatLogSlider\n",
"frs <- mkFloatRangeSlider\n",
"setField fns StepFloat 0.25\n",
"-- We can set the base of the logslider\n",
"setField fls BaseFloat 2\n",
"setField fls StepFloat 1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"metadata": {},
"outputs": [],
"source": [
"ins\n",
"irs"
"irs\n",
"fns\n",
"fls\n",
"frs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"They work the same as the previous widgets plus, they are a lot more confortable if you have bounds. The only difference is with the pair ones, we have to get the `IntPairValue` and `FloatPairValue` fields"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
"metadata": {},
"outputs": [],
"source": [
"getField irs IntPairValue\n",
"getField frs FloatPairValue"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"getField irs IntPairValue"
"-- We can also set the field!\n",
"setField irs IntPairValue (32,42)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### `IntProgress`"
"Let's create a small program using widgets that gives us the greatest common divisor of two numbers! It displays the result on a `IntText` widget"
"This widget is meant to be used as a progress bar."
"#### `IntProgress` and `FloatProgress`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, we have these two widgets, that we can use as progress bars."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
"metadata": {},
"outputs": [],
"source": [
"fnp <- mkFloatProgress\n",
"fnp"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"setField fnp FloatValue 42.5\n",
"getField fnp FloatValue"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also display them Vertically.\n",
"\n",
"*(Did you know you can also display the Sliders vertically?)*"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"setField fnp Orientation VerticalOrientation"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we are going to create a REAL progress bar! For example, let's create a thread that does some incredible complex calculations (sleeping) and then reports the progress to the widget"