## 2.8 UI Composition with Delegates (or Views and Controllers)

As we saw before, it is possible to compose the interface for your application using multiple views; this holds true whether the view has an associated controller or not. I'm not going to provide an example embedding views and controllers because it's not very enlightening; it is easy to extend the original UI Composition example to use controller associated to the views, and that example is much more interesting if adapted to a ObjectList.

Since delegates inherit from views, it is also possible to compose a delegate with multiple child delegates (and even mix and match them with views). The requirement that the parent delegate be based on glade is the same, too: you should subclass `GladeDelegate` for your main window, though any kind of view can be attached to it.

The nice part about doing UI composition using delegates is that the interface and interaction is well encapsulated in a single class, and if you are careful when writing a child delegate, you can reuse that class in as many places of your applications as you like. I'm going to use the ObjectList from the last example to build a (rather fake) news browsing application in the next example:

    #!/usr/bin/env python
    import os

    import gtk

    from kiwi.ui import gadgets
    from kiwi.ui.delegates import Delegate, SlaveDelegate
    from kiwi.ui.objectlist import ObjectList, Column

    class NewsItem:
        def __init__(self, title, author, url):
            self.title, self.author, self.url = title, author, url

    # Friendly Pigdog.org news
    news = [
     NewsItem("Smallpox Vaccinations for EVERYONE", "JRoyale",
              "http://www.pigdog.org/auto/Power_Corrupts/link/2700.html"),
     NewsItem("Is that uranium in your pocket or are you just happy to see me?",
              "Baron Earl",
              "http://www.pigdog.org/auto/bad_people/link/2699.html"),
     NewsItem("Cut 'n Paste", "Baron Earl",
              "http://www.pigdog.org/auto/ArtFux/link/2690.html"),
     NewsItem("A Slippery Exit", "Reverend CyberSatan",
              "http://www.pigdog.org/auto/TheCorporateFuck/link/2683.html"),
     NewsItem("Those Crazy Dutch Have Resurrected Elvis", "Miss Conduct",
              "http://www.pigdog.org/auto/viva_la_musica/link/2678.html")
    ]

    my_columns = [Column("title", sorted=True, tooltip="Title of article", width=50),
                  Column("author", tooltip="Author of article"),
                  Column("url", title="Address", visible=False,
                         tooltip="Address of article")]

    class Shell(Delegate):
        widgets = ["ok", "cancel", "header", "footer", "title"]
        def __init__(self):
            Delegate.__init__(self, gladefile="news_shell",
                              delete_handler=self.quit_if_last)

            # paint header and footer; they are eventboxes that hold a
            # label and buttonbox respectively
            gadgets.set_background(self.header, "white")
            gadgets.set_background(self.footer, "#A0A0A0")
            gadgets.set_foreground(self.title, "blue")

            # Create the delegate and set it up
            objectlist = ObjectList(my_columns, news)
            objectlist.connect('selection-changed', self.news_selected)
            objectlist.connect('double-click', self.double_click)
            slave = SlaveDelegate(toplevel=objectlist)

            self.attach_slave("placeholder", slave)
            slave.focus_toplevel() # Must be done after attach

            self.slave = slave

        def news_selected(self, the_list, item):
            objectlist = self.slave.get_toplevel()
            print "%s %s %s\n" % (item.title, item.author, item.url)

        def double_click(self, the_list, selected_object):
            self.emit('result', selected_object.url)
            self.hide_and_quit()

        def on_ok__clicked(self, *args):
            objectlist = self.slave.get_toplevel()
            item = objectlist.get_selected()
            if item:
                self.emit('result', item.url)
            self.hide_and_quit()

        def on_cancel__clicked(self, *args):
            self.hide_and_quit()

    url = None
    shell = Shell()
    shell.show_all()
    def get_url(view, result):
        global url
        url = result

    shell.connect('result', get_url)

    gtk.main()

    if url is not None:
        # Try to run BROWSER (or lynx) on the URL returned
        browser = os.environ.get("BROWSER", "lynx")
        os.system("%s %s" % (browser, url))

Let's have a quick look at the code:

1. I create a list of instances and the columns specification; I then define a class for the news shell, inheriting from `GladeDelegate`.
2. In the constructor I show off some cosmetic features of Kiwi (the "header" widget is an eventbox, in which the label is a child; look at the glade file for more details).
3. I create and attach the slave, storing a reference to it in the instance variable "slave", and set focus up.
4. I define handlers for the buttons, and the simple handler `row_selected()` for the `select_row` signal, which will be called when a row is selected.
5. I create and run the `Shell`, which renders the interface. When the interface closes, I catch the return value `retval` and use it as input to run a browser for the selected news item (okay, so the app is not really a browser, I lied).

This example shows a lot of the power of Kiwi; in a few lines, and with a little work in Glade, we have a working application that looks decent, behaves well and isn't hard to maintain. The next section will go on describing Proxies, which are high-level Views that represent an instance or part of it.