diff --git a/notebooks/ComplexUIExample.ipynb b/notebooks/ComplexUIExample.ipynb
new file mode 100644
index 0000000..c6d90b7
--- /dev/null
+++ b/notebooks/ComplexUIExample.ipynb
@@ -0,0 +1,96 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Demonstration of Blocking UI\n",
+ "\n",
+ "File `ui.py` in this folder implements a blocking User Interface that asks user to select a color. If no action happens within 10 seconds default value is returned.\n",
+ "\n",
+ "Run this notebook using `Cell -> Run All` menu option."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from ipywidgets import HTML\n",
+ "from ui import blocking_ui\n",
+ "\n",
+ "color, mode = blocking_ui(default='beige', timeout=3)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if mode == 'user':\n",
+ " print(f\"So you picked '{color}'\")\n",
+ "else:\n",
+ " print('Try to click faster next time')\n",
+ "\n",
+ "HTML(f'''\n",
+ "
{color}
''')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# this cell throws Exception\n",
+ "print(no_such_var)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"This cell should not execute\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "print(\"This won't run either\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "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.6.8"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/notebooks/test-ui-poll.ipynb b/notebooks/test-ui-poll.ipynb
deleted file mode 100644
index f89c8c0..0000000
--- a/notebooks/test-ui-poll.ipynb
+++ /dev/null
@@ -1,89 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "import ipywidgets as w\n",
- "from IPython.display import display\n",
- "from jupyter_ui_poll import run_ui_poll_loop"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "from ui import make_sample_ui\n",
- "\n",
- "def poll_cbk():\n",
- " \"\"\" This function is called 10 times a second\n",
- " \"\"\"\n",
- " if state.color is not None:\n",
- " return state.color, 'user'\n",
- " \n",
- " with state.dbg:\n",
- " print('.', end=\"\", flush=True)\n",
- " progress = state.progress\n",
- " progress.value += 0.1\n",
- " if progress.max - progress.value <= 3:\n",
- " progress.bar_style = 'danger'\n",
- " if progress.value >= progress.max:\n",
- " with state.dbg:\n",
- " print(\"\\nTimes UP!\")\n",
- " return 'beige', 'timeout'\n",
- " return None\n",
- "\n",
- "state = make_sample_ui()\n",
- "display(state.ui)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "cc, mode = run_ui_poll_loop(poll_cbk, sleep=0.1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "if mode == 'user':\n",
- " print(f\"So you picked '{cc}'\")\n",
- "else:\n",
- " print('Try to click faster next time')\n",
- "w.HTML(f'''\n",
- "{cc}
''')"
- ]
- }
- ],
- "metadata": {
- "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.6.8"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/notebooks/ui.py b/notebooks/ui.py
index 5b226d6..9de2cd5 100644
--- a/notebooks/ui.py
+++ b/notebooks/ui.py
@@ -1,7 +1,10 @@
""" Sample UI used in the example notebook.
"""
+import time
from types import SimpleNamespace
import ipywidgets as w
+from IPython.display import display
+from jupyter_ui_poll import run_ui_poll_loop
def make_sample_ui(width="600px"):
@@ -26,7 +29,7 @@ def make_sample_ui(width="600px"):
progress = w.FloatProgress(value=0,
min=0,
- max=10,
+ max=1,
description='',
layout=w.Layout(width='100%'))
lbl = w.HTML('Pick your favorite food color
',
@@ -53,3 +56,47 @@ def mk_btn(color):
state.dbg],
layout=w.Layout(width=width, overflow='hidden'))
return state
+
+
+def blocking_ui(default='beige', timeout=10):
+ """ Displays a UI then blocks until user makes a choice or timeout happens.
+
+ Returns
+ =======
+ (color, 'user') if user selects a color in time
+ (default, 'timeout') in case of a timeout
+ """
+ state = make_sample_ui()
+
+ def poll_cbk():
+ """ This function is called 10 times a second
+ """
+ if state.color is not None: # User selected some color
+ return state.color, 'user'
+ # no action from user so far
+
+ # update progress bar
+ progress = state.progress
+ progress.value = progress.max*(time.time() - state.t_start)/timeout
+
+ if progress.value > 0.7*progress.max:
+ if progress.bar_style != 'danger':
+ with state.dbg:
+ print('Hurry!!!')
+
+ progress.bar_style = 'danger'
+
+ if progress.value >= progress.max:
+ with state.dbg:
+ print("\nTimes UP!")
+ return default, 'timeout' # Terminate -- out of time
+
+ # continue polling
+ return None
+
+ display(state.ui)
+ state.t_start = time.time()
+
+ # call poll_cbk @ 25 fps,
+ # process 4 ui events between calls
+ return run_ui_poll_loop(poll_cbk, 1/25, 4)