##// END OF EJS Templates
Fab CSS
Fab CSS

File last commit:

r14377:956f7392
r14445:108ab2b1
Show More
Dialogs.ipynb
199 lines | 6.8 KiB | text/plain | TextLexer

Simple example notebook that shows how one can use widgets to build custom dialogs.

In [1]:
from IPython.html import widgets
from IPython.display import display

By using Bootstrap's modal class and ContainerWidgets, we can build a simple dialog window.

In [2]:
def scrub_text_html(text):
    text = text.replace('&', '&')
    text = text.replace(' ', ' ')
    text = text.replace('<', '&lt;')
    text = text.replace('>', '&gt;')
    text = text.replace('\n', '<br>\n')
    return text

def create_dialog(title=None, on_hidden=None):
    dialog = widgets.ContainerWidget(visible=False)
    dialog_header = widgets.ContainerWidget(parent=dialog)
    dialog_header_close = widgets.ButtonWidget(parent=dialog_header, description = '&times;')
    dialog_header_label = widgets.StringWidget(parent=dialog_header, default_view_name='LabelView')
    dialog_body = widgets.ContainerWidget(parent=dialog)
    dialog_footer = widgets.ContainerWidget(parent=dialog)
    
    if title is None or title == '':
        title = ' '
    dialog_header_label.value = '<h3>%s</h3>' % scrub_text_html(title)
    
    def handle_close():
        dialog.visible = False
        if on_hidden is not None:
            on_hidden(dialog)
    dialog_header_close.on_click(handle_close)
    
    display(dialog)
    
    dialog_header.add_class('modal-header')
    dialog_body.add_class('modal-body')
    dialog_footer.add_class('modal-footer')
    dialog.add_class('modal')
    
    dialog_header_close.remove_class('btn')
    dialog_header_close.add_class('close')
    
    return dialog_body, dialog_footer, dialog

Using this show_dialog method, custom dialogs can be made using widgets. Below is an example of a Yes/No dialog.

In [3]:
# Since Python has a global thread lock, everything runs on a single thread.
# Because of this, we use an asynronous model (callbacks).
def show_yes_no(prompt, yes_callback=None, no_callback=None, title=None):
    
    def handle_hidden(dialog_window):
        if no_callback is not None:
            no_callback()
        dialog_window.close()
        
    (dialog_body, dialog_footer, dialog_window) = create_dialog(title=title, on_hidden=handle_hidden)
    
    def handle_yes():
        dialog_window.visible = False
        if yes_callback is not None:
            yes_callback()
        dialog_window.close()
            
    def handle_no():
        dialog_window.visible = False
        handle_hidden(dialog_window)
    
    yes_button = widgets.ButtonWidget(parent=dialog_footer, description='Yes')
    yes_button.on_click(handle_yes)
    no_button = widgets.ButtonWidget(parent=dialog_footer, description='No')
    no_button.on_click(handle_no)
    prompt_label = widgets.StringWidget(parent=dialog_body, value=scrub_text_html(prompt), default_view_name='LabelView')
    
    display(yes_button)
    display(no_button)
    display(prompt_label)
    
    yes_button.add_class('btn-success')
    no_button.add_class('btn-danger')
    
    dialog_window.visible=True
    
    

Test

In [4]:
def yes():
    show_yes_no("Do you want to show the dialog again?", yes, title="Self displaying dialog")
yes()

Dialog result handlers can contain nested dialogs. The following example shows how syncronous logic can be simulated using closures.

In [5]:
title = "Interactive Story"
def open_door():
    show_yes_no("The house is empty.  You are tired and decide to sleep.  You live to see another day.")

def stay_outside():
    def fight():
        show_yes_no("You try to fight the wolves but die in the process.", title=title)
        
    def panic():
        def flight():
            show_yes_no("You run as fast as you can.  You manage to escape the\n" + \
                        "wolves but the cold is beginning to get to you.  You\n" + \
                        "sit in the snow to take a nap.  You freeze and die.", title=title)
        
        show_yes_no("You panic.  Do you enter the cabin now?", open_door, flight, title=title)
        
    show_yes_no("A pack of wolves approach.  Do you want to fight them?", fight, panic, title=title)

show_yes_no("You are standing outside in a blizzard on a cold winter night.\n" + \
            "A warm cabin with the lights on is in front of you.\n\n" + \
            "Do you want to enter the cabin?", open_door, stay_outside, title=title)