def unload_modules_and_display_notification(self, display_on): modules_removed = self.unload_all_imported_modules() if len(modules_removed) > 0: mods = ', '.join(['<em>{0}</em>'.format(name) for name in modules_removed]) noty.noty(Html('Unloaded the following modules: {0}'.format(mods)), type='success', timeout=2000, layout='bottomCenter').show_on(display_on) else: noty.noty(Html('No modules to unload'), type='success', timeout=2000, layout='bottomCenter').show_on(display_on)
def pres(self, pres_ctx): options = {} if self.__disabled is not False: options['disabled'] = True if self.__primary_icon is not None or self.__secondary_icon is not None: icons = {} if self.__primary_icon is not None: icons['primary'] = self.__primary_icon if self.__secondary_icon is not None: icons['secondary'] = self.__secondary_icon options['icons'] = icons if self.__text is not None: p = Html( '<button type="button" onclick="{0}">'.format( post_event_js_code_for_handler('clicked')), self.__text, '</button>').js_function_call('larch.controls.initButton', options) else: options['text'] = False p = Html('<button type="button" onclick="{0}"></button>' ).js_function_call('larch.controls.initButton', options) p = p.with_event_handler('clicked', self.clicked).use_js( '/static/larch/larch_ui.js').use_css('/static/larch/larch_ui.css') return p
def iframe(self, width=None, height=None): p = Html('<div class="deck-container">').extend( self.__slides).append('</div>') p = p.js_function_call('init_deck_js').use_js(source=_deck_js) p = _deck_libs(p, self.__extensions, self.__style, self.__transition) p = PresIFrame(p, width, height) return p
def pres(self, pres_ctx): css = ' class="{0}"'.format( self.__css_class) if self.__css_class is not None else '' p = Html('<a {2}href="javascript:" onclick="{0}">{1}</a>'.format( post_event_js_code_for_handler('clicked'), self.__link_text, css)) p = p.with_event_handler('clicked', self.clicked) return p
def audio_capture_button(num_channels, format, audio_data_callback): """ Create an audio capture button :param num_channels: the number of channels; 1 = mono, 2 = stereo :param format: the data format; valid formats are provided by constants in the larch.media.audio module: FORMAT_WAV: WAV file format FORMAT_RAW8: raw data, 8-bit signed integer per sample per channel FORMAT_RAW16: raw data, 16-bit signed integer per sample per channel, FORMAT_RAWF32: raw data, 32-bit float per sample per channel audio_data_callback - a callback function that is invoked when audio data is received from the browser, of the form function(data_file, sample_rate, num_samples, num_channels), where: data_file - an object that contains the audio data, has a read method, the same kind of object as used to form file uploads. sample_rate - the sample rate of the received audio data, in Hz num_samples - the number of samples received; to get length in seconds, divide this number by sample_rate num_channels - the number of channels in the received data """ def _submit(event): num_channels = int(event.data['num_channels']) sample_rate = int(event.data['sample_rate']) num_samples = int(event.data['num_samples']) data_file = event.data['data'].file audio_data_callback(data_file, sample_rate, num_samples, num_channels) if format not in _valid_formats: raise ValueError, 'Unknown audio format \'{0}\''.format(format) button = Html('<button></button>').js_function_call( 'larch.media.initAudioCaptureButton', num_channels, format) button = button.with_event_handler('form_submit', _submit) button = button.use_js('/static/larch/larch_media.js') return button
def present_exception_with_traceback(exc, val, tb): traceback_str = '<br>\n'.join(Html.escape_str(traceback.format_exc(tb)).split('\n')) content = Html('<span class="exception_name">{0}</span>'.format(type(exc).__name__), '<br>', '<span class="exception_message">{0}</span>'.format(Html.escape_str(exc.message)), '<br>', '<span class="exception_message">{0}</span>'.format(Html.escape_str(str(val))), '<br>', '<div class="exception_traceback">{0}</div>'.format(traceback_str)) return error_box('Exception', content)
def result(): s = self.state.value if s is True: hdr = Html( '<button onclick="{0}" style="width: 100%; text-align: left">' .format(post_event_js_code_for_handler('clicked')), self.__header, '</button>') hdr = hdr.js_function_call( 'larch.controls.initButton', {'icons': { 'primary': 'ui-icon-minus' }}) hdr = hdr.with_event_handler('clicked', on_clicked) ct = Html('<div class="dropdown_expander_content">', self.__content, '</div>') return Html(hdr, ct) elif s is False: hdr = Html( '<button onclick="{0}" style="width: 100%; text-align: left">' .format(post_event_js_code_for_handler('clicked')), self.__header, '</button>') hdr = hdr.js_function_call( 'larch.controls.initButton', {'icons': { 'primary': 'ui-icon-plus' }}) hdr = hdr.with_event_handler('clicked', on_clicked) return hdr else: raise TypeError, 'drop down expander: state type unknown'
def pres(self, pres_ctx): fragment = pres_ctx.fragment_view menu_bar_contents = [] right_menu_bar_contents = [] # Liveliness indicator def _toggle_liveliness(event_name, ev_data): pres_ctx.fragment_view.page.page_js_function_call('larch.toggleLiveliness') liveliness_indicator = Html('<div class="larch_liveliness_indicator larch_liveliness_off">LIVE</div>').js_function_call('larch.initLivelinessToggle') right_menu_bar_contents.append(liveliness_indicator) # Documentation if self.__app_context.documentation_url is not None: doc_link = Html('<a class="__larch_app_doc_link" href="{0}">Documentation</a>'.format(self.__app_context.documentation_url)) right_menu_bar_contents.append(doc_link) # Command bar button cmd_bar_button = Html('<button class="__larch_app_cmd_bar_button">Cmd. bar (Esc)</button>').js_function_call("larch.controls.initToggleCommandBarButton") right_menu_bar_contents.append(cmd_bar_button) # Logout link if self.__app_context.logout_url_path is not None: #right_menu_bar_contents.append(Html('<div class="__larch_app_frame_logout_link"><a href="{0}">Logout</a></div>'.format(self.__logout_url_path))) right_menu_bar_contents.append(Html('<a href="{0}">Logout</a>'.format(self.__app_context.logout_url_path)).js_eval('$(node).button();')) # Build the menu bar contents by iterating through the focii, accumulating them as we go by concatenating the results of calling the __menu_bar_cumulative_contents__ method for f in self.__focii: try: method = f.__menu_bar_cumulative_contents__ except AttributeError: pass else: menu_bar_contents.extend(method(fragment)) # Add the result of calling __menu_bar_contents__ on the final focus try: method = self.__page.__menu_bar_contents__ except AttributeError: pass else: menu_bar_contents.extend(method(fragment.page, fragment)) # Generate the menu bar main_menu_bar = self.__menu_bar_contents_to_table(menu_bar_contents) right_menu_bar = self.__menu_bar_contents_to_table(right_menu_bar_contents) return Html( '<div class="__larch_app_frame_page_header">', '<span class="__larch_cmd_bar_right">', right_menu_bar, '</span>', main_menu_bar, '</div>', '<img src="/static/1px_transparent.png">', '<div class="larch_frame_page_content">', self.__page, '</div>' ).use_css(url='/static/larch/larch_app_frame.css')
def link(self, link_content): p = Html('<div class="deck-container">').extend( self.__slides).append('</div>') p = p.js_function_call('init_deck_js').use_js(source=_deck_js) p = _deck_libs(p, self.__extensions, self.__style, self.__transition) p = PresLink(p, link_content) return p
def pres(self, pres_ctx): sz = '' if self.__width is not None: sz = ' style="width: {0};"'.format(self.__width) p = Html('<input type="text" value="{0}"{1}></input>'.format(self.__text, sz)).js_function_call('larch.controls.initTextEntry', self.__immediate_events, self.__channel) p = p.with_event_handler('text_entry_edit', lambda event: self.edit(event, event.data)) p = p.use_js('/files/static/larch/larch_ui.js').use_css('/files/static/larch/larch_ui.css') return p
def __present__(self, fragment): self.__incr.on_access() header = Html('<div class="notebook_python_code_header">Python code (executable)</div>') code = Html('<div class="notebook_python_code_container notebook_code_container">', self.__code, '</div>') res = ['<div class="notebook_result_container">', self.__result, '</div>'] if self.__result is not None else [] p = Html(*(['<div class="notebook_code_block">', header, '<div class="notebook_code_block_body">', code] + res + ['</div></div>'])) p = focusable.focusable(p) return p
def pres(self, pres_ctx): p = Html('<form enctype="multipart/form-data">', self.__contents, '</form>').js_function_call( 'larch.controls.initForm').with_event_handler( 'form_submit', self.submit) p = p.use_js('/static/jquery/js/jquery.form.min.js').use_js( '/static/larch/larch_ui.js').use_css('/static/larch/larch_ui.css') return p
def exception_to_html_src(exc, val, tb): traceback_str = '<br>\n'.join(Html.escape_str(traceback.format_exc(tb)).split('\n')) val_str = '<br>\n'.join(Html.escape_str(str(val)).split('\n')) content = ('<span class="exception_name">{0}</span><br>' + \ '<span class="exception_message">{1}</span><br>' + \ '<span class="exception_message">{2}</span><br>' + \ '<div class="exception_traceback">{3}</div>').format(type(exc).__name__, Html.escape_str(exc.message), val_str, traceback_str) return exc_box_to_html_src('Exception', content)
def pres(self, pres_ctx): p = Html( *(['<select>'] + self.__options + ['</select>'])).js_function_call('larch.controls.initSelect') p = p.with_event_handler('select_choose', lambda event: self.choose(event, event.data)) p = p.use_js('/static/larch/larch_ui.js').use_css( '/static/larch/larch_ui.css') return p
def pres(self, pres_ctx): p = Html(self.__contents).js_function_call( 'larch.controls.initFocusable').js_shutdown_function_call( 'larch.controls.shutdownFocusable') p = p.with_event_handler('gain_focus', self.gain_focus) p = p.with_event_handler('lose_focus', self.lose_focus) p = p.use_js('/static/larch/larch_ui.js').use_css( '/static/larch/larch_ui.css') return p
def __doc_table_row(self, doc, page): def on_save(event): doc.save_and_display_notification(page) save_button = button.button('Save', on_save) doc_title = '<a href="/pages/{0}/{1}" class="larch_app_doc_title">{2}</a>'.format(self.loc_prefix, doc.location, doc.name) doc_filename = '<span class="larch_app_doc_filename">{0}</span><span class="larch_app_doc_extension">.ularch</span>'.format(doc.filename) controls = Html('<div class="larch_app_doc_controls">', save_button, '</div>') return Html('<tr class="larch_app_doc"> <td>', doc_title, '</td><td>', doc_filename, '</td><td>', controls, '</td></tr>')
def exception_to_html_src(exc, val, tb): traceback_str = '<br>\n'.join( Html.escape_str(traceback.format_exc(tb)).split('\n')) val_str = '<br>\n'.join(Html.escape_str(str(val)).split('\n')) content = ('<span class="exception_name">{0}</span><br>' + \ '<span class="exception_message">{1}</span><br>' + \ '<span class="exception_message">{2}</span><br>' + \ '<div class="exception_traceback">{3}</div>').format(type(exc).__name__, Html.escape_str(exc.message), val_str, traceback_str) return exc_box_to_html_src('Exception', content)
def pres(self, pres_ctx): spin = Html('<input name={0} value={1} />'.format( self.__input_name, self.__value)) spin = spin.js_function_call('larch.controls.initSpinner', self.__channel) spin = spin.with_event_handler("spinner_change", self.__on_spinner_change) spin = spin.use_js('/static/larch/larch_ui.js').use_css( '/static/larch/larch_ui.css') return spin
def __menu_bar_contents_to_table(self, menu_bar_contents): # Generate the menu bar if len(menu_bar_contents) > 0: contents = ['<table><tr>'] for x in menu_bar_contents: contents.extend(['<td class="__larch_app_frame_menu_bar">', x, '</td>']) contents.append('</tr></table>') return Html(*contents) else: return Html()
def __present__(self, fragment): def _on_reload(event): self.__user_docs.reload() if self.__docs is not None: self.__docs.reload() reset_button = button.button('Reload', _on_reload) reset_section = Html('<div>', reset_button, '</div>') add_notebook = menu.item('Notebook', lambda event: self.__tools.add(NewDocumentTool(self.__user_docs, notebook.Notebook, 'Notebook'))) add_project = menu.item('Project', lambda event: self.__tools.add(NewDocumentTool(self.__user_docs, project_root.ProjectRoot, 'Project'))) new_item = menu.sub_menu('New', [add_notebook, add_project]) new_document_menu = menu.menu([new_item], drop_down=True) upload_ipynb = menu.item('Upload', lambda event: self.__tools.add(UploadIPynbTool(self.__user_docs))) web_ipynb = menu.item('Download from web', lambda event: self.__tools.add(DownloadIPynbFromWebTool(self.__user_docs))) import_ipynb_item = menu.sub_menu('Import IPython notebook', [upload_ipynb, web_ipynb]) import_ipynb_menu = menu.menu([import_ipynb_item], drop_down=True) document_controls = Html('<table class="larch_app_controls_row"><tr><td class="larch_app_control">', new_document_menu, '</td>', '<td class="larch_app_control">', import_ipynb_menu, '</td></tr></table>') contents = [""" <div class="larch_app_title_bar">The Ubiquitous Larch</div> <div class="larch_app_enclosure"> <section class="larch_app_docs_section"> <h2>Open documents:</h2> """, reset_section, self.__user_docs, document_controls, self.__tools, """</section> <section> <p>For more information on using the Ubiquitous Larch, please see the <a href="/pages/docs/index">documentation</a>.</p> </section> <p class="larch_app_powered_by">The Ubiquitous Larch © copyright Geoffrey French<br/> Powered by <a class="larch_app_pwr_link" href="http://www.python.org">Python</a>, <a class="larch_app_pwr_link" href="http://flask.pocoo.org">Flask</a>/<a class="larch_app_pwr_link" href="http://bottlepy.org">Bottle</a>/<a class="larch_app_pwr_link" href="http://www.djangoproject.com/">Django</a>, <a class="larch_app_pwr_link" href="http://jquery.com/">jQuery</a>, <a class="larch_app_pwr_link" href="http://www.json.org/js.html">json.js</a>, <a class="larch_app_pwr_link" href="http://codemirror.net/">Code Mirror</a>, <a class="larch_app_pwr_link" href="http://ckeditor.com/">ckEditor</a>, <a class="larch_app_pwr_link" href="http://d3js.org/">d3.js</a>, <a class="larch_app_pwr_link" href="http://imakewebthings.com/deck.js/">deck.js</a> and <a class="larch_app_pwr_link" href="http://needim.github.io/noty/">noty</a></p> </div> """] return Html(*contents).use_css(url=larch_app_css)
def present_exception_with_traceback(exc, val, tb): traceback_str = '<br>\n'.join( Html.escape_str(traceback.format_exc(tb)).split('\n')) content = Html( '<span class="exception_name">{0}</span>'.format(type(exc).__name__), '<br>', '<span class="exception_message">{0}</span>'.format( Html.escape_str(exc.message)), '<br>', '<span class="exception_message">{0}</span>'.format( Html.escape_str(str(val))), '<br>', '<div class="exception_traceback">{0}</div>'.format(traceback_str)) return error_box('Exception', content)
def pres(self, pres_ctx): sz = '' if self.__width is not None: sz = ' style="width: {0};"'.format(self.__width) p = Html('<input type="text" value="{0}"{1}></input>'.format( self.__text, sz)).js_function_call('larch.controls.initTextEntry', self.__immediate_events, self.__channel) p = p.with_event_handler('text_entry_edit', lambda event: self.edit(event, event.data)) p = p.use_js('/static/larch/larch_ui.js').use_css( '/static/larch/larch_ui.css') return p
def present_python_object(x, fragment_view): if hasattr(x, '__dict__'): attr_names = sorted(x.__dict__.keys()) attrs = [_field(name, x) for name in attr_names] attrs = Html(*attrs) t = Html.div(dropdown_expander(Html('Type'), type(x))) a = Html.div(dropdown_expander(Html('Attributes'), attrs)) if attrs is not None else None s = Html.div(dropdown_expander(Html('repr'), present_string(repr(x)))) return Html('<div class="pythonobject">', Html(t, a, s) if a is not None else Html(t, s), '</div>') else: t = Html.div(dropdown_expander(Html('Type'), type(x))) s = Html.div(present_string(repr(x))) return Html('<div class="pythonobject">', Html(t, s), '</div>')
def _inspector_entry(fragment): model = fragment.model destination = console.PythonConsole() destination.add_binding('m', model) model_is_presentable = isinstance(model, Pres) model_type_css_class = 'inspector_model_pres' if model_is_presentable else 'inspector_model_python' model_type_descr = ' (presentation type)' if model_is_presentable else ' (a Python object)' model_descr = Html('<span class="{0}">{1}</span>{2}<br><span class="inspector_id">id: {3}</span>'.format(model_type_css_class, type(model).__name__, model_type_descr, id(model))) rsc = resource.PresLink(destination, model_descr) anchor = rsc.js_function_call('larch.controls.initInspectorEntry', fragment.segment_id) return Html('<li>', anchor, '</li>')
def present_tuple(xs): if len(xs) == 0: return Html(_open_paren + _close_paren) if len(xs) == 1: return Html(_open_paren, xs[0], _comma + _close_paren) else: contents = [_open_paren] first = True for x in xs: if not first: contents.append(_comma_space) contents.append(x) first = False contents.append(_close_paren) return Html(*contents)
def present_string(x): xx = cgi.escape(x) print 'TODO: handle escape characters when presenting strings' if '\n' in x: lines = [ u'<span class="pyprim_string">{0}</span>'.format(line) for line in xx.split('\n') ] lines[0] = _triple_quote + lines[0] lines[-1] += _triple_quote lines = [u'<div>{0}</div>'.format(line) for line in lines] return Html(u''.join(lines)) else: return Html(_quote + u'<span class="pyprim_string">{0}</span>'.format(xx) + _quote)
def __present__(self, fragment): def on_execute(event): self.__console._execute_current_block(self) def on_execute_key(event, key): on_execute(event) return True code_area = Html('<div>', self.__code, '</div>') execute_button = button.button('Execute', on_execute) code_area_with_key_handler = code_area.with_key_handler( [KeyAction(KeyAction.KEY_DOWN, 13, ctrl=True)], on_execute_key) return Html('<div>', code_area_with_key_handler, execute_button, '</div>')
def __present__(self, fragment): super_pres = super(ProjectRoot, self).__present__(fragment) def on_merge_upload(event): def on_upload(event, name, fp): self._merge_from_file(name, fp) dialog.dialog.close_containing_dialog(event) def on_cancel(event): dialog.dialog.close_containing_dialog(event) chooser = file_chooser.upload_file_chooser(on_upload, on_cancel) dialog.dialog(Html('<h3>Choose file to merge</h3>', chooser)).show_on(event) def on_merge_download(event): def on_downloaded(event, name, fp): self._merge_from_file(name, fp) dialog.dialog.close_containing_dialog(event) def on_cancel(event): dialog.dialog.close_containing_dialog(event) chooser = file_chooser.fetch_from_web_file_chooser(on_downloaded, on_cancel) dialog.dialog(Html('<h3>Enter URL to download file to merge</h3>', chooser)).show_on(event) def _on_set_package_name(event, name): self.__set_python_package_name_no_incr_change(name) def _on_unload(event): subject = fragment.subject try: unload_modules_and_display_notification = subject.document.unload_modules_and_display_notification except AttributeError: print 'WARNING: Could not unload_all_imported_modules; method unavailable' raise else: unload_modules_and_display_notification(fragment) merge_upload_button = button.button('Merge from file (upload)', on_merge_upload) merge_download_button = button.button('Merge from web', on_merge_download) python_package_name = self.python_package_name python_package_name = python_package_name if python_package_name is not None else '' entry = text_entry.text_entry(python_package_name, on_edit=_on_set_package_name) unload_button = button.button('Unload', _on_unload) contents = [ '<div class="larch_app_title_bar"><h1 class="page_title">Project</h1></div>', '<p class="project_control">Merge in contents from other file: ', merge_upload_button, ' ', merge_download_button, '</p>', '<p class="project_root_package_name">Root package name: ', entry, '<br><span class="notes_text">(this is the base name from which the contents of this project will be importable)</span></p>', '<p class="project_control">Unload modules imported from project (Esc - U): ', unload_button, '</p>', super_pres, ] return Html(*contents).use_css(url="/static/larch/project.css")
def __present__(self, fragment): contents = ['<div>Change grooup'] for change in self._changes: contents.append('<br>') contents.append(change) contents.append('</div>') return Html(*contents)
def separator(): """ Create a separator menu item :return: the separator """ p = Html('<li></li>') return p
def _get_console_notifications(self): if self.__bindings is not None: return Html().extend([ self.__binding_notification(*binding) for binding in self.__bindings ]) else: return None
def _present_header_contents(self, fragment): project_location = fragment.subject.location path_to_root = self.path_to_root trail = list(reversed([node.name for node in path_to_root[:-1]])) page_location = '/'.join([project_location] + trail) return Html('<a class="project_page_text" href="{0}">{1}</a>'.format( page_location, self.name))
def __present__(self, fragment): self.__incr.on_access() contents = ['<table class="larch_app_doc_list">'] contents.append('<thead class="larch_app_doc_list_header"><td>Title</td><td>Filename</td><td>Save</td></thead>') contents.append('<tbody>') contents.extend([self.__doc_table_row(doc, fragment.page) for doc in self.__documents]) contents.append('</tbody></table>') return Html(*contents)
def present_float(x): s = str(x) if 'e' in s: return _present_si_real(s, s.index('e')) elif 'E' in s: return _present_si_real(s, s.index('E')) else: return Html('<span class="pyprim_float">{0}</span>'.format(s))
def pres(self, pres_ctx): options = {} if self.__disabled is not False: options['disabled'] = True if self.__primary_icon is not None or self.__secondary_icon is not None: icons = {} if self.__primary_icon is not None: icons['primary'] = self.__primary_icon if self.__secondary_icon is not None: icons['secondary'] = self.__secondary_icon options['icons'] = icons if self.__text is not None: p = Html('<button type="button" onclick="{0}">'.format(post_event_js_code_for_handler('clicked')), self.__text, '</button>').js_function_call('larch.controls.initButton', options) else: options['text'] = False p = Html('<button type="button" onclick="{0}"></button>').js_function_call('larch.controls.initButton', options) p = p.with_event_handler('clicked', self.clicked).use_js('/files/static/larch/larch_ui.js').use_css('/files/static/larch/larch_ui.css') return p
def pres(self, pres_ctx): if self.__width is None: div = Html('<div></div>') else: div = Html('<div style="width: {0};"></div>'.format(self.__width)) div = div.js_function_call('larch.controls.initSlider', True, self.__options, self.__channel) div = div.with_event_handler("slider_change", lambda event: self.release(event, event.data)) div = div.with_event_handler("slider_slide", lambda event: self.slide(event, event.data)) div = div.use_js('/files/static/larch/larch_ui.js').use_css('/files/static/larch/larch_ui.css') return div
def pres(self, pres_ctx): css = ' class="{0}"'.format(self.__css_class) if self.__css_class is not None else '' p = Html('<a {2}href="javascript:" onclick="{0}">{1}</a>'.format(post_event_js_code_for_handler('clicked'), self.__link_text, css)) p = p.with_event_handler('clicked', self.clicked) return p
def present_exception_no_traceback(exc): content = Html('<span class="exception_name">{0}</span>'.format(type(exc).__name__), '<br>', '<span class="exception_message">{0}</span>'.format(Html.escape_str(exc.message))) return error_box('Exception', content)
def pres(self, pres_ctx): p = Html(*(['<select>'] + self.__options + ['</select>'])).js_function_call('larch.controls.initSelect') p = p.with_event_handler('select_choose', lambda event: self.choose(event, event.data)) p = p.use_js('/files/static/larch/larch_ui.js').use_css('/files/static/larch/larch_ui.css') return p