예제 #1
0
class PanelBasicExample(VerticalLayout, IClickListener):

    def __init__(self):
        super(PanelBasicExample, self).__init__()

        self.setSpacing(True)

        # Panel 1 - with caption
        self._panel = Panel('This is a standard Panel')
        self._panel.setHeight('200px')  # we want scrollbars
        # let's adjust the panels default layout (a VerticalLayout)
        layout = self._panel.getContent()
        layout.setMargin(True)  # we want a margin
        layout.setSpacing(True)  # and spacing between components
        self.addComponent(self._panel)

        # Let's add a few rows to provoke scrollbars:
        for _ in range(20):
            l = Label('The quick brown fox jumps over the lazy dog.')
            self._panel.addComponent(l)

        # Caption toggle:
        b = Button('Toggle caption')
        b.addListener(self, IClickListener)
        self.addComponent(b)


    def buttonClick(self, event):
        if self._panel.getCaption() == '':
            self._panel.setCaption('This is a standard Panel')
        else:
            self._panel.setCaption('')
예제 #2
0
파일: ui_panel.py 프로젝트: rwl/traitsui
def panel(ui):
    """Creates a panel-based Muntjac user interface for a specified UI object.
       This function does not modify the UI object passed to it.  The object
       returned may be either a component or None.
    """
    # Bind the context values to the 'info' object:
    ui.info.bind_context()

    # Get the content that will be displayed in the user interface:
    content = ui._groups
    nr_groups = len(content)

    if nr_groups == 0:
        panel = None
    if nr_groups == 1:
        panel = _GroupPanel(content[0], ui).control
    elif nr_groups > 1:
        panel = TabSheet()
        _fill_panel(panel, content, ui)
        panel.ui = ui

    # If the UI is scrollable then wrap the panel in a Panel.
    if ui.scrollable and panel is not None:
        sa = Panel()
        sa.addComponent(panel)
#        sa.getParent().setResizable(True)
        panel = sa

    return panel
예제 #3
0
class PanelLightExample(VerticalLayout, IClickListener):

    def __init__(self):
        super(PanelLightExample, self).__init__()

        self.setSpacing(True)
        self.setSpacing(True)

        # Panel 1 - with caption
        self._panel = Panel('This is a light Panel')
        self._panel.setStyleName(Reindeer.PANEL_LIGHT)
        self._panel.setHeight('200px')  # we want scrollbars
        # let's adjust the panels default layout (a VerticalLayout)
        layout = self._panel.getContent()
        layout.setMargin(True)  # we want a margin
        layout.setSpacing(True)
        # and spacing between components
        self.addComponent(self._panel)

        # Let's add a few rows to provoke scrollbars:
        for _ in range(20):
            l = Label('The quick brown fox jumps over the lazy dog.')
            self._panel.addComponent(l)

        # Caption toggle:
        b = Button('Toggle caption')
        b.addListener(self, IClickListener)
        self.addComponent(b)


    def buttonClick(self, event):
        if self._panel.getCaption() is None:
            self._panel.setCaption('This is a light Panel')
        else:
            self._panel.setCaption(None)
예제 #4
0
    def __init__(self):
        super(ApplicationLayoutWindow, self).__init__()

        # Our main layout is a horizontal layout
        main = HorizontalLayout()
        main.setSizeFull()
        self.setContent(main)

        # Tree to the left
        treePanel = Panel()  # for scrollbars
        treePanel.setStyleName(Reindeer.PANEL_LIGHT)
        treePanel.setHeight('100%')
        treePanel.setWidth(None)
        treePanel.getContent().setSizeUndefined()
        self.addComponent(treePanel)

        tree = Tree()
        tree.setContainerDataSource(ExampleUtil.getHardwareContainer())
        tree.setItemCaptionPropertyId(ExampleUtil.hw_PROPERTY_NAME)
        for idd in tree.rootItemIds():
            tree.expandItemsRecursively(idd)
        treePanel.addComponent(tree)

        # vertically divide the right area
        left = VerticalLayout()
        left.setSizeFull()
        self.addComponent(left)
        main.setExpandRatio(left, 1.0)  # use all available space

        # table on top
        tbl = Table()
        tbl.setWidth('100%')
        tbl.setContainerDataSource(ExampleUtil.getISO3166Container())
        tbl.setSortDisabled(True)
        tbl.setPageLength(7)
        left.addComponent(tbl)

        # Label on bottom
        textPanel = Panel()  # for scrollbars
        textPanel.setStyleName(Reindeer.PANEL_LIGHT)
        textPanel.setSizeFull()
        left.addComponent(textPanel)
        left.setExpandRatio(textPanel, 1.0)  # use all available space

        text = Label(ExampleUtil.lorem, Label.CONTENT_XHTML)
        text.setWidth('500px')  # some limit is good for text
        textPanel.addComponent(text)
    def __init__(self):
        super(ApplicationLayoutWindow, self).__init__()

        # Our main layout is a horizontal layout
        main = HorizontalLayout()
        main.setSizeFull()
        self.setContent(main)

        # Tree to the left
        treePanel = Panel()  # for scrollbars
        treePanel.setStyleName(Reindeer.PANEL_LIGHT)
        treePanel.setHeight('100%')
        treePanel.setWidth(None)
        treePanel.getContent().setSizeUndefined()
        self.addComponent(treePanel)

        tree = Tree()
        tree.setContainerDataSource(ExampleUtil.getHardwareContainer())
        tree.setItemCaptionPropertyId(ExampleUtil.hw_PROPERTY_NAME)
        for idd in tree.rootItemIds():
            tree.expandItemsRecursively(idd)
        treePanel.addComponent(tree)

        # vertically divide the right area
        left = VerticalLayout()
        left.setSizeFull()
        self.addComponent(left)
        main.setExpandRatio(left, 1.0)  # use all available space

        # table on top
        tbl = Table()
        tbl.setWidth('100%')
        tbl.setContainerDataSource(ExampleUtil.getISO3166Container())
        tbl.setSortDisabled(True)
        tbl.setPageLength(7)
        left.addComponent(tbl)

        # Label on bottom
        textPanel = Panel()  # for scrollbars
        textPanel.setStyleName(Reindeer.PANEL_LIGHT)
        textPanel.setSizeFull()
        left.addComponent(textPanel)
        left.setExpandRatio(textPanel, 1.0)  # use all available space

        text = Label(ExampleUtil.lorem, Label.CONTENT_XHTML)
        text.setWidth('500px')  # some limit is good for text
        textPanel.addComponent(text)
예제 #6
0
    def __init__(self):
        super(CssLayoutsExample, self).__init__()

        self.setMargin(True)

        # Note, that this code example may not be self explanatory without
        # checking out the related CSS file in the sampler theme.

        panel = Panel('Panel')
        panel.setStyleName('floatedpanel')
        panel.setWidth('30%')
        panel.setHeight('370px')
        panel.addComponent(
            Label('This panel is 30% wide ' +
                  'and 370px high (defined on the server side) ' +
                  'and floated right (with custom css). ' +
                  'Try resizing the browser window to see ' +
                  'how the black boxes (floated left) ' +
                  'behave. Every third of them has colored text ' +
                  'to demonstrate the dynamic css injection.'))

        bottomCenter = Label(
            'I\'m a 3 inches wide footer at the bottom of the layout')
        bottomCenter.setSizeUndefined()  # disable 100% default width
        bottomCenter.setStyleName('footer')

        cssLayout = MyCssLayout()
        cssLayout.setWidth('100%')

        cssLayout.addComponent(panel)
        for _ in range(15):
            # add black labels that float left
            cssLayout.addComponent(Brick())

        cssLayout.addComponent(bottomCenter)

        self.addComponent(cssLayout)
예제 #7
0
    def __init__(self):
        super(CssLayoutsExample, self).__init__()

        self.setMargin(True)

        # Note, that this code example may not be self explanatory without
        # checking out the related CSS file in the sampler theme.

        panel = Panel('Panel')
        panel.setStyleName('floatedpanel')
        panel.setWidth('30%')
        panel.setHeight('370px')
        panel.addComponent(Label('This panel is 30% wide '
                + 'and 370px high (defined on the server side) '
                + 'and floated right (with custom css). '
                + 'Try resizing the browser window to see '
                + 'how the black boxes (floated left) '
                + 'behave. Every third of them has colored text '
                + 'to demonstrate the dynamic css injection.'))

        bottomCenter = Label(
                'I\'m a 3 inches wide footer at the bottom of the layout')
        bottomCenter.setSizeUndefined()  # disable 100% default width
        bottomCenter.setStyleName('footer')

        cssLayout = MyCssLayout()
        cssLayout.setWidth('100%')

        cssLayout.addComponent(panel)
        for _ in range(15):
            # add black labels that float left
            cssLayout.addComponent(Brick())

        cssLayout.addComponent(bottomCenter)

        self.addComponent(cssLayout)
예제 #8
0
    def __init__(self):
        super(IconsExample, self).__init__()

        self.setSpacing(True)

        # Button w/ icon
        button = Button('Save')
        button.setIcon(ThemeResource('../sampler/icons/action_save.gif'))
        self.addComponent(button)

        # Label
        l = Label('Icons are very handy')
        l.setCaption('Comment')
        l.setIcon(ThemeResource('../sampler/icons/comment_yellow.gif'))
        self.addComponent(l)

        # Panel w/ links
        p = Panel('Handy links')
        p.setIcon(ThemeResource('../sampler/icons/icon_info.gif'))
        self.addComponent(p)
        lnk = Link('http://vaadin.com',
                   ExternalResource('http://www.vaadin.com'))
        lnk.setIcon(ThemeResource('../sampler/icons/icon_world.gif'))
        p.addComponent(lnk)
        lnk = Link('http://vaadin.com/learn',
                   ExternalResource('http://www.vaadin.com/learn'))
        lnk.setIcon(ThemeResource('../sampler/icons/icon_world.gif'))
        p.addComponent(lnk)
        lnk = Link('http://dev.vaadin.com/',
                   ExternalResource('http://dev.vaadin.com/'))
        lnk.setIcon(ThemeResource('../sampler/icons/icon_world.gif'))
        p.addComponent(lnk)
        lnk = Link('http://vaadin.com/forum',
                   ExternalResource('http://vaadin.com/forum'))
        lnk.setIcon(ThemeResource('../sampler/icons/icon_world.gif'))
        p.addComponent(lnk)
예제 #9
0
    def __init__(self):
        super(IconsExample, self).__init__()

        self.setSpacing(True)

        # Button w/ icon
        button = Button('Save')
        button.setIcon(ThemeResource('../sampler/icons/action_save.gif'))
        self.addComponent(button)

        # Label
        l = Label('Icons are very handy')
        l.setCaption('Comment')
        l.setIcon(ThemeResource('../sampler/icons/comment_yellow.gif'))
        self.addComponent(l)

        # Panel w/ links
        p = Panel('Handy links')
        p.setIcon(ThemeResource('../sampler/icons/icon_info.gif'))
        self.addComponent(p)
        lnk = Link('http://vaadin.com',
                ExternalResource('http://www.vaadin.com'))
        lnk.setIcon(ThemeResource('../sampler/icons/icon_world.gif'))
        p.addComponent(lnk)
        lnk = Link('http://vaadin.com/learn',
                ExternalResource('http://www.vaadin.com/learn'))
        lnk.setIcon(ThemeResource('../sampler/icons/icon_world.gif'))
        p.addComponent(lnk)
        lnk = Link('http://dev.vaadin.com/',
                ExternalResource('http://dev.vaadin.com/'))
        lnk.setIcon(ThemeResource('../sampler/icons/icon_world.gif'))
        p.addComponent(lnk)
        lnk = Link('http://vaadin.com/forum',
                ExternalResource('http://vaadin.com/forum'))
        lnk.setIcon(ThemeResource('../sampler/icons/icon_world.gif'))
        p.addComponent(lnk)
예제 #10
0
    def createPanel(self, number):
        p = Panel('Panel %d' % number)
        p.getContent().setSpacing(True)

        # Let's create a customized shortcut that jumps to the next field
        p.addAction(NextFieldListener("Next field", KeyCode.ARROW_DOWN, None))

        # Firstname input with an input prompt for demo clarity
        firstname = TextField('Firstname')
        firstname.setInputPrompt('ALT-SHIFT-F to focus')
        p.addComponent(firstname)

        # Using firstname.addShortcutListener() would add globally,
        # but we want the shortcut only in this panel:
        p.addAction(
            FocusShortcut(firstname, KeyCode.F, ModifierKey.ALT,
                          ModifierKey.SHIFT))

        # additinally we'll add a global shortcut for this field using the
        # shorthand notation (^1 == CTRL-1,NextFieldListener etc)
        firstname.addShortcutListener(
            FocusShortcut(firstname, 'Focus panel &_' + str(number)))
        p.setDescription('CTRL-' + str(number) + ' to focus')

        # Lastname input with an input prompt for demo clarity
        lastname = TextField('Lastname')
        lastname.setInputPrompt('ALT-SHIFT-L to focus')
        p.addComponent(lastname)

        # Using firstname.addShortcutListener() would add globally,
        # but we want the shortcut only in this panel:
        p.addAction(
            FocusShortcut(lastname, KeyCode.L, ModifierKey.ALT,
                          ModifierKey.SHIFT))

        # Button with a simple click-listener
        save = Button('Save', SaveListener(self, p))
        p.addComponent(save)

        # setClickShortcut() would add global shortcut, instead we
        # 'scope' the shortcut to the panel:
        p.addAction(
            ClickShortcut(save, KeyCode.S, ModifierKey.ALT, ModifierKey.SHIFT))

        return p
예제 #11
0
    def createPanel(self, number):
        p = Panel('Panel %d' % number)
        p.getContent().setSpacing(True)

        # Let's create a customized shortcut that jumps to the next field
        p.addAction(NextFieldListener("Next field", KeyCode.ARROW_DOWN, None))

        # Firstname input with an input prompt for demo clarity
        firstname = TextField('Firstname')
        firstname.setInputPrompt('ALT-SHIFT-F to focus')
        p.addComponent(firstname)

        # Using firstname.addShortcutListener() would add globally,
        # but we want the shortcut only in this panel:
        p.addAction(FocusShortcut(firstname, KeyCode.F, ModifierKey.ALT,
                ModifierKey.SHIFT))

        # additinally we'll add a global shortcut for this field using the
        # shorthand notation (^1 == CTRL-1,NextFieldListener etc)
        firstname.addShortcutListener(FocusShortcut(firstname,
                'Focus panel &_' + str(number)))
        p.setDescription('CTRL-' + str(number) + ' to focus')

        # Lastname input with an input prompt for demo clarity
        lastname = TextField('Lastname')
        lastname.setInputPrompt('ALT-SHIFT-L to focus')
        p.addComponent(lastname)

        # Using firstname.addShortcutListener() would add globally,
        # but we want the shortcut only in this panel:
        p.addAction(FocusShortcut(lastname, KeyCode.L, ModifierKey.ALT,
                ModifierKey.SHIFT))

        # Button with a simple click-listener
        save = Button('Save', SaveListener(self, p))
        p.addComponent(save)

        # setClickShortcut() would add global shortcut, instead we
        # 'scope' the shortcut to the panel:
        p.addAction(ClickShortcut(save, KeyCode.S, ModifierKey.ALT,
                ModifierKey.SHIFT))

        return p
예제 #12
0
class FeatureView(HorizontalLayout):

    _MSG_SHOW_SRC = 'View Source'

    def __init__(self):
        super(FeatureView, self).__init__()

        self._right = None
        self._left = None
        self._controls = None
        self._title = Label("", Label.CONTENT_XHTML)
        self._showSrc = None
        self._exampleCache = dict()
        self._currentFeature = None
        self._srcWindow = None

        self.setWidth('100%')
        self.setMargin(True)
        self.setSpacing(True)
        self.setStyleName('sample-view')

        self._left = VerticalLayout()
        self._left.setWidth('100%')
        self._left.setSpacing(True)
        self._left.setMargin(False)
        self.addComponent(self._left)
        self.setExpandRatio(self._left, 1)

        rightLayout = VerticalLayout()
        self._right = Panel(rightLayout)
        rightLayout.setMargin(True, False, False, False)
        self._right.setStyleName(Reindeer.PANEL_LIGHT)
        self._right.addStyleName('feature-info')
        self._right.setWidth('319px')
        self.addComponent(self._right)

        self._controls = HorizontalLayout()
        self._controls.setWidth('100%')
        self._controls.setStyleName('feature-controls')

        self._title.setStyleName('title')
        self._controls.addComponent(self._title)
        self._controls.setExpandRatio(self._title, 1)

        resetExample = NativeButton('Reset', ResetListener(self))
        resetExample.setStyleName(BaseTheme.BUTTON_LINK)
        resetExample.addStyleName('reset')
        resetExample.setDescription('Reset Sample')
        self._controls.addComponent(resetExample)
        self._showSrc = ActiveLink()
        self._showSrc.setDescription(
            'Right / middle / ctrl / shift -click for browser window/tab')

        self._showSrc.addListener(ShowSrcListener(self),
                                  ILinkActivatedListener)
        self._showSrc.setCaption(self._MSG_SHOW_SRC)
        self._showSrc.addStyleName('showcode')
        self._showSrc.setTargetBorder(Link.TARGET_BORDER_NONE)
        self._controls.addComponent(self._showSrc)

    def showSource(self, source):
        if self._srcWindow is None:
            self._srcWindow = Window('Python source')
            self._srcWindow.getContent().setSizeUndefined()
            self._srcWindow.setWidth('70%')
            self._srcWindow.setHeight('60%')
            self._srcWindow.setPositionX(100)
            self._srcWindow.setPositionY(100)

        self._srcWindow.removeAllComponents()
        self._srcWindow.addComponent(CodeLabel(source))

        if self._srcWindow.getParent() is None:
            self.getWindow().addWindow(self._srcWindow)

    def resetExample(self):
        if self._currentFeature is not None:
            w = self.getWindow()
            w.removeSubwindows()
            f = self._currentFeature
            self._currentFeature = None
            if f in self._exampleCache:
                del self._exampleCache[f]
            self.setFeature(f)

    def setFeature(self, feature):

        from muntjac.demo.sampler.SamplerApplication import SamplerApplication

        if feature != self._currentFeature:
            self._currentFeature = feature
            self._right.removeAllComponents()
            self._left.removeAllComponents()

            self._left.addComponent(self._controls)
            self._title.setValue('<span>' + feature.getName() + '</span>')
            #            if feature.getSinceVersion().isNew():
            #                self._title.addStyleName('new')
            #            else:
            #                self._title.removeStyleName('new')

            self._left.addComponent(self.getExampleFor(feature))

            self._right.setCaption('Description and Resources')

            # Do not show parent description if it's directly inside the root
            alll = SamplerApplication.getAllFeatures()
            parent = alll.getParent(feature)
            isRoot = alll.getParent(parent) is None
            desc = parent.getDescription()
            hasParentDesc = False

            if parent is not None and not isRoot:
                parentLabel = Label(parent.getDescription())
                if desc is not None and desc != '':
                    parentLabel.setContentMode(Label.CONTENT_XHTML)
                    self._right.addComponent(parentLabel)
                    hasParentDesc = True
            desc = feature.getDescription()
            if desc is not None and desc != '':
                # Sample description uses additional decorations if a parent
                # description is found
                l = Label(
                    ("<div class=\"outer-deco\"><div class=\"deco\">"
                     "<span class=\"deco\"></span>") + desc + "</div></div>",
                    Label.CONTENT_XHTML)
                self._right.addComponent(l)
                if hasParentDesc:
                    l.setStyleName('sample-description')
                else:
                    l.setStyleName('description')

            # open src in new window -link
            self._showSrc.setTargetName(self._currentFeature.getFragmentName())
            er = ExternalResource(self.getApplication().getURL() + 'src/' +
                                  self._currentFeature.getFragmentName())
            self._showSrc.setResource(er)

            resources = feature.getRelatedResources()
            if resources is not None:
                res = VerticalLayout()
                self.caption = Label("<span>Additional Resources</span>",
                                     Label.CONTENT_XHTML)
                self.caption.setStyleName('section')
                self.caption.setWidth('100%')
                res.addComponent(self.caption)
                res.setMargin(False, False, True, False)
                for r in resources:
                    l = Link(r.getName(), r)
                    l.setIcon(ThemeResource('../runo/icons/16/note.png'))
                    res.addComponent(l)
                self._right.addComponent(res)

            apis = feature.getRelatedAPI()
            if apis is not None:
                api = VerticalLayout()
                self.caption = Label("<span>API Documentation</span>",
                                     Label.CONTENT_XHTML)
                self.caption.setStyleName('section')
                self.caption.setWidth('100%')
                api.addComponent(self.caption)
                api.setMargin(False, False, True, False)
                for r in apis:
                    l = Link(r.getName(), r)
                    ic = ThemeResource('../runo/icons/16/document-txt.png')
                    l.setIcon(ic)
                    api.addComponent(l)
                self._right.addComponent(api)

            features = feature.getRelatedFeatures()
            if features is not None:
                rel = VerticalLayout()
                self.caption = Label("<span>Related Samples</span>",
                                     Label.CONTENT_XHTML)
                self.caption.setStyleName('section')
                self.caption.setWidth('100%')
                rel.addComponent(self.caption)
                rel.setMargin(False, False, True, False)
                for c in features:
                    f = SamplerApplication.getFeatureFor(c)
                    if f is not None:
                        er = ExternalResource(self.getApplication().getURL() +
                                              '#' + f.getFragmentName())
                        al = ActiveLink(f.getName(), er)
                        if isinstance(f, FeatureSet):
                            ic = ThemeResource('../sampler/icons/category.gif')
                        else:
                            ic = ThemeResource('../sampler/icons/sample.png')
                        al.setIcon(ic)

                        al.addListener(LinkListener(self, f),
                                       ILinkActivatedListener)
                        rel.addComponent(al)
                self._right.addComponent(rel)

    def getExampleFor(self, f):
        ex = self._exampleCache.get(f)
        if ex is None:
            ex = f.getExample()
            self._exampleCache[f] = ex
        return ex
예제 #13
0
class FeatureView(HorizontalLayout):

    _MSG_SHOW_SRC = 'View Source'

    def __init__(self):
        super(FeatureView, self).__init__()

        self._right = None
        self._left = None
        self._controls = None
        self._title = Label("", Label.CONTENT_XHTML)
        self._showSrc = None
        self._exampleCache = dict()
        self._currentFeature = None
        self._srcWindow = None

        self.setWidth('100%')
        self.setMargin(True)
        self.setSpacing(True)
        self.setStyleName('sample-view')

        self._left = VerticalLayout()
        self._left.setWidth('100%')
        self._left.setSpacing(True)
        self._left.setMargin(False)
        self.addComponent(self._left)
        self.setExpandRatio(self._left, 1)

        rightLayout = VerticalLayout()
        self._right = Panel(rightLayout)
        rightLayout.setMargin(True, False, False, False)
        self._right.setStyleName(Reindeer.PANEL_LIGHT)
        self._right.addStyleName('feature-info')
        self._right.setWidth('319px')
        self.addComponent(self._right)

        self._controls = HorizontalLayout()
        self._controls.setWidth('100%')
        self._controls.setStyleName('feature-controls')

        self._title.setStyleName('title')
        self._controls.addComponent(self._title)
        self._controls.setExpandRatio(self._title, 1)

        resetExample = NativeButton('Reset', ResetListener(self))
        resetExample.setStyleName(BaseTheme.BUTTON_LINK)
        resetExample.addStyleName('reset')
        resetExample.setDescription('Reset Sample')
        self._controls.addComponent(resetExample)
        self._showSrc = ActiveLink()
        self._showSrc.setDescription('Right / middle / ctrl / shift -click for browser window/tab')

        self._showSrc.addListener(ShowSrcListener(self), ILinkActivatedListener)
        self._showSrc.setCaption(self._MSG_SHOW_SRC)
        self._showSrc.addStyleName('showcode')
        self._showSrc.setTargetBorder(Link.TARGET_BORDER_NONE)
        self._controls.addComponent(self._showSrc)


    def showSource(self, source):
        if self._srcWindow is None:
            self._srcWindow = Window('Python source')
            self._srcWindow.getContent().setSizeUndefined()
            self._srcWindow.setWidth('70%')
            self._srcWindow.setHeight('60%')
            self._srcWindow.setPositionX(100)
            self._srcWindow.setPositionY(100)

        self._srcWindow.removeAllComponents()
        self._srcWindow.addComponent( CodeLabel(source) )

        if self._srcWindow.getParent() is None:
            self.getWindow().addWindow(self._srcWindow)


    def resetExample(self):
        if self._currentFeature is not None:
            w = self.getWindow()
            w.removeSubwindows()
            f = self._currentFeature
            self._currentFeature = None
            if f in self._exampleCache:
                del self._exampleCache[f]
            self.setFeature(f)


    def setFeature(self, feature):

        from muntjac.demo.sampler.SamplerApplication import SamplerApplication

        if feature != self._currentFeature:
            self._currentFeature = feature
            self._right.removeAllComponents()
            self._left.removeAllComponents()

            self._left.addComponent(self._controls)
            self._title.setValue('<span>' + feature.getName() + '</span>')
            if feature.getSinceVersion().isNew():
                self._title.addStyleName('new')
            else:
                self._title.removeStyleName('new')

            self._left.addComponent(self.getExampleFor(feature))

            self._right.setCaption('Description and Resources')

            # Do not show parent description if it's directly inside the root
            alll = SamplerApplication.getAllFeatures()
            parent = alll.getParent(feature)
            isRoot = alll.getParent(parent) is None
            desc = parent.getDescription()
            hasParentDesc = False

            if parent is not None and not isRoot:
                parentLabel = Label(parent.getDescription())
                if desc is not None and desc != '':
                    parentLabel.setContentMode(Label.CONTENT_XHTML)
                    self._right.addComponent(parentLabel)
                    hasParentDesc = True
            desc = feature.getDescription()
            if desc is not None and desc != '':
                # Sample description uses additional decorations if a parent
                # description is found
                l = Label(("<div class=\"outer-deco\"><div class=\"deco\">"
                        "<span class=\"deco\"></span>")
                        + desc + "</div></div>", Label.CONTENT_XHTML)
                self._right.addComponent(l)
                if hasParentDesc:
                    l.setStyleName('sample-description')
                else:
                    l.setStyleName('description')

            # open src in new window -link
            self._showSrc.setTargetName(self._currentFeature.getFragmentName())
            er = ExternalResource(self.getApplication().getURL()
                    + 'src/' + self._currentFeature.getFragmentName())
            self._showSrc.setResource(er)

            resources = feature.getRelatedResources()
            if resources is not None:
                res = VerticalLayout()
                self.caption = Label("<span>Additional Resources</span>",
                        Label.CONTENT_XHTML)
                self.caption.setStyleName('section')
                self.caption.setWidth('100%')
                res.addComponent(self.caption)
                res.setMargin(False, False, True, False)
                for r in resources:
                    l = Link(r.getName(), r)
                    l.setIcon( ThemeResource('../runo/icons/16/note.png') )
                    res.addComponent(l)
                self._right.addComponent(res)

            apis = feature.getRelatedAPI()
            if apis is not None:
                api = VerticalLayout()
                self.caption = Label("<span>API Documentation</span>",
                        Label.CONTENT_XHTML)
                self.caption.setStyleName('section')
                self.caption.setWidth('100%')
                api.addComponent(self.caption)
                api.setMargin(False, False, True, False)
                for r in apis:
                    l = Link(r.getName(), r)
                    ic = ThemeResource('../runo/icons/16/document-txt.png')
                    l.setIcon(ic)
                    api.addComponent(l)
                self._right.addComponent(api)

            features = feature.getRelatedFeatures()
            if features is not None:
                rel = VerticalLayout()
                self.caption = Label("<span>Related Samples</span>",
                        Label.CONTENT_XHTML)
                self.caption.setStyleName('section')
                self.caption.setWidth('100%')
                rel.addComponent(self.caption)
                rel.setMargin(False, False, True, False)
                for c in features:
                    f = SamplerApplication.getFeatureFor(c)
                    if f is not None:
                        er = ExternalResource(self.getApplication().getURL()
                                + '#' + f.getFragmentName())
                        al = ActiveLink(f.getName(), er)
                        if isinstance(f, FeatureSet):
                            ic = ThemeResource('../sampler/icons/category.gif')
                        else:
                            ic = ThemeResource('../sampler/icons/sample.png')
                        al.setIcon(ic)

                        al.addListener(LinkListener(self, f),
                                ILinkActivatedListener)
                        rel.addComponent(al)
                self._right.addComponent(rel)


    def getExampleFor(self, f):
        ex = self._exampleCache.get(f)
        if ex is None:
            ex = f.getExample()
            self._exampleCache[f] = ex
        return ex