{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[Index](Index.ipynb) - [Back](Widget Events.ipynb) - [Next](Custom Widget - Hello World.ipynb)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "%%html\n",
    "<style>\n",
    ".example-container { background: #999999; padding: 2px; min-height: 100px; }\n",
    ".example-container.sm { min-height: 50px; }\n",
    ".example-box { background: #9999FF; width: 50px; height: 50px; text-align: center; vertical-align: middle; color: white; font-weight: bold; margin: 2px;}\n",
    ".example-box.med { width: 65px; height: 65px; }   \n",
    ".example-box.lrg { width: 80px; height: 80px; }   \n",
    "</style>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from IPython.html import widgets\n",
    "from IPython.display import display"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Widget Styling"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Basic styling"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The widgets distributed with IPython can be styled by setting the following traits:\n",
    "\n",
    "- width  \n",
    "- height  \n",
    "- fore_color  \n",
    "- back_color  \n",
    "- border_color  \n",
    "- border_width  \n",
    "- border_style  \n",
    "- font_style  \n",
    "- font_weight  \n",
    "- font_size  \n",
    "- font_family  \n",
    "\n",
    "The example below shows how a `Button` widget can be styled:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "button = widgets.Button(\n",
    "    description='Hello World!',\n",
    "    width=100, # Integers are interpreted as pixel measurements.\n",
    "    height='2em', # em is valid HTML unit of measurement.\n",
    "    color='lime', # Colors can be set by name,\n",
    "    background_color='#0022FF', # and also by color code.\n",
    "    border_color='red')\n",
    "display(button)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Parent/child relationships"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To display widget A inside widget B, widget A must be a child of widget B.  Widgets that can contain other widgets have a **`children` attribute**.  This attribute can be **set via a keyword argument** in the widget's constructor **or after construction**.  Calling display on an **object with children automatically displays those children**, too."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "from IPython.display import display\n",
    "\n",
    "float_range = widgets.FloatSlider()\n",
    "string = widgets.Text(value='hi')\n",
    "container = widgets.Box(children=[float_range, string])\n",
    "\n",
    "container.border_color = 'red'\n",
    "container.border_style = 'dotted'\n",
    "container.border_width = 3\n",
    "display(container) # Displays the `container` and all of it's children."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### After the parent is displayed"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "Children **can be added to parents** after the parent has been displayed.  The **parent is responsible for rendering its children**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "container = widgets.Box()\n",
    "container.border_color = 'red'\n",
    "container.border_style = 'dotted'\n",
    "container.border_width = 3\n",
    "display(container)\n",
    "\n",
    "int_range = widgets.IntSlider()\n",
    "container.children=[int_range]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Fancy boxes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you need to display a more complicated set of widgets, there are **specialized containers** that you can use.  To display **multiple sets of widgets**, you can use an **`Accordion` or a `Tab` in combination with one `Box` per set of widgets** (as seen below).  The \"pages\" of these widgets are their children.  To set the titles of the pages, one can **call `set_title`**."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Accordion"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "name1 = widgets.Text(description='Location:')\n",
    "zip1 = widgets.BoundedIntText(description='Zip:', min=0, max=99999)\n",
    "page1 = widgets.Box(children=[name1, zip1])\n",
    "\n",
    "name2 = widgets.Text(description='Location:')\n",
    "zip2 = widgets.BoundedIntText(description='Zip:', min=0, max=99999)\n",
    "page2 = widgets.Box(children=[name2, zip2])\n",
    "\n",
    "accord = widgets.Accordion(children=[page1, page2])\n",
    "display(accord)\n",
    "\n",
    "accord.set_title(0, 'From')\n",
    "accord.set_title(1, 'To')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### TabWidget"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "name = widgets.Text(description='Name:')\n",
    "color = widgets.Dropdown(description='Color:', options=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'])\n",
    "page1 = widgets.Box(children=[name, color])\n",
    "\n",
    "age = widgets.IntSlider(description='Age:', min=0, max=120, value=50)\n",
    "gender = widgets.RadioButtons(description='Gender:', options=['male', 'female'])\n",
    "page2 = widgets.Box(children=[age, gender])\n",
    "\n",
    "tabs = widgets.Tab(children=[page1, page2])\n",
    "display(tabs)\n",
    "\n",
    "tabs.set_title(0, 'Name')\n",
    "tabs.set_title(1, 'Details')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Alignment"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Most widgets have a **`description` attribute**, which allows a label for the widget to be defined.\n",
    "The label of the widget **has a fixed minimum width**.\n",
    "The text of the label is **always right aligned and the widget is left aligned**:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "display(widgets.Text(description=\"a:\"))\n",
    "display(widgets.Text(description=\"aa:\"))\n",
    "display(widgets.Text(description=\"aaa:\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "If a **label is longer** than the minimum width, the **widget is shifted to the right**:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "display(widgets.Text(description=\"a:\"))\n",
    "display(widgets.Text(description=\"aa:\"))\n",
    "display(widgets.Text(description=\"aaa:\"))\n",
    "display(widgets.Text(description=\"aaaaaaaaaaaaaaaaaa:\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "If a `description` is **not set** for the widget, the **label is not displayed**:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "display(widgets.Text(description=\"a:\"))\n",
    "display(widgets.Text(description=\"aa:\"))\n",
    "display(widgets.Text(description=\"aaa:\"))\n",
    "display(widgets.Text())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Flex boxes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Widgets can be aligned using the `FlexBox`, `HBox`, and `VBox` widgets."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Application to widgets"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Widgets display vertically by default:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "buttons = [widgets.Button(description=str(i)) for i in range(3)]\n",
    "display(*buttons)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Using hbox"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To make widgets display horizontally, you need to **child them to a `HBox` widget**."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "container = widgets.HBox(children=buttons)\n",
    "display(container)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "By setting the width of the container to 100% and its `pack` to `center`, you can center the buttons."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "container.width = '100%'\n",
    "container.pack = 'center'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Visibility"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sometimes it is necessary to **hide or show widgets** in place, **without having to re-display** the widget.\n",
    "The `visible` property of widgets can be used to hide or show **widgets that have already been displayed** (as seen below).  The `visible` property can be:\n",
    "* `True` - the widget is displayed\n",
    "* `False` - the widget is hidden, and the empty space where the widget would be is collapsed\n",
    "* `None` - the widget is hidden, and the empty space where the widget would be is shown"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "w1 = widgets.Latex(value=\"First line\")\n",
    "w2 = widgets.Latex(value=\"Second line\")\n",
    "w3 = widgets.Latex(value=\"Third line\")\n",
    "display(w1, w2, w3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "w2.visible=None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "w2.visible=False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "w2.visible=True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "### Another example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the example below, a form is rendered, which conditionally displays widgets depending on the state of other widgets.  Try toggling the student checkbox."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "form = widgets.VBox()\n",
    "first = widgets.Text(description=\"First Name:\")\n",
    "last = widgets.Text(description=\"Last Name:\")\n",
    "\n",
    "student = widgets.Checkbox(description=\"Student:\", value=False)\n",
    "school_info = widgets.VBox(visible=False, children=[\n",
    "    widgets.Text(description=\"School:\"),\n",
    "    widgets.IntText(description=\"Grade:\", min=0, max=12)\n",
    "    ])\n",
    "\n",
    "pet = widgets.Text(description=\"Pet's Name:\")\n",
    "form.children = [first, last, student, school_info, pet]\n",
    "display(form)\n",
    "\n",
    "def on_student_toggle(name, value):\n",
    "    if value:\n",
    "        school_info.visible = True\n",
    "    else:\n",
    "        school_info.visible = False\n",
    "student.on_trait_change(on_student_toggle, 'value')\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[Index](Index.ipynb) - [Back](Widget Events.ipynb) - [Next](Custom Widget - Hello World.ipynb)"
   ]
  }
 ],
 "metadata": {
  "cell_tags": [
   [
    "<None>",
    null
   ]
  ],
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.4.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
