def column_layout_basics(fixture): """A ColumnLayout turns its Widget into a sequence of columns, each of which is a Div.""" layout = ColumnLayout('column_a', 'column_b') widget = Div(fixture.view) vassert(not widget.children) widget.use_layout(layout) column_a, column_b = widget.children vassert(isinstance(column_a, Div)) vassert(isinstance(column_b, Div))
def __init__(self, view): super().__init__(view) static_div = self.add_child(Div(view)) coactive_div = static_div.add_child(Div(view, css_id='coactive_div')) refreshing_div = self.add_child(RefreshingDiv(view, coactive_div)) text_to_show = 'original' if refreshing_div.fancy_state == 2: text_to_show = 'coactive refreshed' coactive_div.add_child(P(view, text=text_to_show)) fixture.widget = self
def __init__(self, view, nav_layout=None): super(TabbedPanel, self).__init__(view) self.tabs = [] self.nav = self.add_child( Nav(view).use_layout(nav_layout or TabLayout())) self.content_panel = self.add_child(Div(view)) self.content_panel.append_class('tab-content')
def test_page_layout_only_meant_for_html5page(web_fixture): """When an attempting to use a PageLayout on something other than an HTML5Page, a useful exception is raised.""" fixture = web_fixture with expected(IsInstance): Div(fixture.view).use_layout(PageLayout())
def add_pane(self, content_panel, tab): div = content_panel.add_child(Div(self.view)) div.add_child(tab.contents) div.append_class('tab-pane') div.set_id(tab.css_id) div.add_attribute_source(ActiveStateAttributes(tab, active_class='active')) return div
def add_column(self, name, size=None, offsets=None, vertical_align=None, column_widget=None): """Called to add a column with given options. :param name: (See :class:`ColumnOptions`) :keyword size: (See :class:`ColumnOptions`) :keyword offsets: (See :class:`ColumnOptions`) :keyword vertical_align: (See :class:`ColumnOptions`) :keyword column_widget: If given, this Widget is added as the column instead of a Div (the default). .. versionchanged:: 4.0 Changed to create a named column with all possible options. """ column_options = ColumnOptions(name, size=size, offsets=offsets, vertical_align=vertical_align) if ResponsiveSize.wraps_for_some_device_class(self.added_column_definitions+[column_options]): self.add_clearfix(column_options) column = self.widget.add_child(column_widget or Div(self.view)) column_options.size.add_css_classes(column, prefix='col') column_options.offsets.add_css_classes(column, prefix='offset') column_options.vertical_align.add_css_classes(column) self.added_column_definitions.append(column_options) self.columns[column_options.name] = column column.append_class('column-%s' % column_options.name) if self.add_slots: column.add_child(Slot(self.view, column_options.name)) return column
def add_column(self, size): """Add an un-named column, with the given :class:`ResponsiveSize`. :keyword size: The sizes to use for the column. Returns a :class:`reahl.web.ui.Div` representing the added column. """ return self.widget.add_child(Div(self.view))
def __init__(self, view): super().__init__(view) self.enable_refresh() self.add_child(Div(view, css_id='inner_div')) self.layout.add_input( TextInput(self, fixture.model_object.fields.some_trigger_field, refresh_widget=self))
def add_clearfix(self, column_size): clearfix = self.widget.add_child(Div(self.view)) clearfix.append_class('clearfix') for device_class in DeviceClass.all_classes(): if ResponsiveSize.wraps_for(device_class, self.added_sizes + [column_size]): clearfix.append_class('visible-%s-block' % device_class.class_label)
def column_slots(fixture): """A ColumnLayout can be made that adds a Slot to each added column, named after the column it is added to.""" widget = Div(fixture.view).use_layout( ColumnLayout('column_name_a', 'column_name_b').with_slots()) column_a, column_b = widget.layout.columns.values() vassert('column_name_a' in column_a.available_slots) vassert('column_name_b' in column_b.available_slots)
def test_no_javascript_when_no_chart_on_page(web_fixture): """When there aren't any Charts on the page, the plotly.js src should not be present.""" wsgi_app = web_fixture.new_wsgi_app(child_factory=Div.factory(), enable_js=True) web_fixture.reahl_server.set_app(wsgi_app) browser = web_fixture.driver_browser browser.open('/') assert browser.get_xpath_count(plotly_js) == 0
def add_contents_of_tab_to(self, content_panel, tab): assert tab.menu_item, 'add the tab to a menu first before adding its contents' div = content_panel.add_child(Div(self.view)) div.add_child(tab.contents) div.append_class('tab-pane') div.set_attribute('role', 'tabpanel') div.set_id(tab.css_id) div.add_attribute_source(ActiveStateAttributes(tab, active_value='active')) div.set_attribute('aria-labelledby', '%s' % tab.menu_item.a.css_id) return div
def add_clearfix(self, column_options): clearfix = self.widget.add_child(Div(self.view)) clearfix.append_class('clearfix') wrapping_classes = [device_class for device_class in DeviceClass.all_classes() if ResponsiveSize.wraps_for(device_class, self.added_column_definitions + [column_options])] if wrapping_classes: device_class = wrapping_classes[0] if device_class.one_smaller: clearfix.append_class(device_class.one_smaller.as_combined_css_class(['hidden'], [])) return clearfix
def adding_unnamed_columns(fixture): """You can add a column by calling add_column on the ColumnLayout""" widget = Div(fixture.view).use_layout(ColumnLayout()) vassert(not widget.children) widget.layout.add_column(ResponsiveSize()) vassert(len(widget.children) == 1) vassert(isinstance(widget.children[0], Div))
def test_widget_layout(web_fixture): """A Layout is used to add children to the Widget in customised ways, and to customise the Widget itself upon construction.""" class MyLayout(Layout): def customise_widget(self): self.widget.append_class('class-added-by-custom-layout') def add_wrapped(self, child): wrapper = self.widget.add_child(Div(self.view)) wrapper.add_child(child) return child fixture = web_fixture widget_with_layout = Div(fixture.view) assert not widget_with_layout.has_attribute('class') assert not widget_with_layout.children widget_with_layout.use_layout(MyLayout()) assert widget_with_layout.get_attribute( 'class') == 'class-added-by-custom-layout' assert not widget_with_layout.children widget_to_add = P(fixture.view) widget_with_layout.layout.add_wrapped(widget_to_add) [wrapper] = widget_with_layout.children assert wrapper.children == [widget_to_add]
def coactive_widgets_cannot_be_parents(self): """The ancestor Widgets of a given Widget cannot be its coactive Widgets.""" grandparent = self.page.add_child(Div(self.view, css_id='grandparent')) parent = grandparent.add_child( CoactiveWidgetStub(self.view, 'parent', [])) child = parent.add_child( CoactiveWidgetStub(self.view, 'child', [grandparent])) self.result_widget = child self.expected_coactive_widgets = None self.expected_exception = ProgrammerError self.expected_exception_regex = 'The coactive Widgets of .+ include its ancestor\(s\): .+'
def order_of_columns(fixture): """Columns are added in the order given to the ColumnLayout constructor, and the Div representing each column can be obtained using dictionary access on Layout.columns.""" widget = Div(fixture.view).use_layout( ColumnLayout('column_name_a', 'column_name_b')) column_a = widget.layout.columns['column_name_a'] column_b = widget.layout.columns['column_name_b'] first_column, second_column = widget.children vassert(first_column is column_a) vassert(second_column is column_b)
def customise_widget(self): self.document = self.widget.body.add_child(Div(self.view)) self.document.set_id('doc') if self.document_layout: self.document.use_layout(self.document_layout) self.header = self.document.add_child(Header(self.view)) self.header.add_child(Slot(self.view, 'header')) self.header.set_id('hd') if self.header_layout: self.header.use_layout(self.header_layout) self.contents = self.document.add_child(Div(self.view)) if self.contents_layout: self.contents.use_layout(self.contents_layout) self.contents.set_id('bd') self.contents.set_attribute('role', 'main') self.footer = self.document.add_child(Footer(self.view)) self.footer.add_child(Slot(self.view, 'footer')) self.footer.set_id('ft') if self.footer_layout: self.footer.use_layout(self.footer_layout)
def __init__(self, view, figure, css_id, read_check=None, write_check=None): super().__init__(view, read_check=read_check, write_check=write_check) self.figure = figure containing_div = self.add_child(Div(view, css_id=css_id)) containing_div.append_class('reahl-plotlychart') self.set_html_representation(containing_div) self.enable_refresh() containing_div.add_child( LiteralHTML(view, PlotlyJS.get_instance().inline_material())) self.contents = containing_div.add_child(ChartContents( self)) #: The contents of the graph. You can use this as
def widget_layout_errors(fixture): """A Layout can only be used with a single Widget, and a Widget can only have a single Layout.""" widget_with_layout = Div(fixture.view).use_layout(Layout()) with expected(ProgrammerError): widget_with_layout.use_layout(Layout()) re_used_layout = Layout() widget_with_reused_layout = Div(fixture.view).use_layout(re_used_layout) with expected(ProgrammerError): Div(fixture.view).use_layout(re_used_layout)
def column_layout_sizes(fixture): """You can also pass tuples to define columns with specified sizes. The size is passed to add_column which you can override.""" fixture.added_sizes = [] @stubclass(ColumnLayout) class ColumnLayoutStub(ColumnLayout): def add_column(self, size): fixture.added_sizes.append(size) return super(ColumnLayoutStub, self).add_column(size) specified_size = EmptyStub() widget = Div(fixture.view).use_layout( ColumnLayoutStub('column_a', ('column_b', specified_size))) vassert(isinstance(fixture.added_sizes[0], ResponsiveSize)) vassert(not fixture.added_sizes[0]) vassert(fixture.added_sizes[1] is specified_size)
def columns_classes(fixture): """The Div added for each column specified to ColumnLayout is given a CSS class derived from the column name.""" widget = Div(fixture.view).use_layout(ColumnLayout('column_name_a')) column_a = widget.layout.columns['column_name_a'] vassert('column-column_name_a' in column_a.get_attribute('class'))
def assemble(self, **ui_arguments): self.controller_at_assemble_time = self.controller root = self.define_view('/some/path', title='A view') root.set_slot('slotA', Div.factory()) self.assembled = True
def customise_widget(self): for slot_name in self.slots: slot_div = self.widget.body.add_child(Div(self.view)) slot_div.append_class('column-%s' % slot_name) slot_div.add_child(Slot(self.view, slot_name))
def add_wrapped(self, child): wrapper = self.widget.add_child(Div(self.view)) wrapper.add_child(child) return child
def new_page(self): return Div(self.view)