What is the black header widget in some programs?

In some of the ubuntu programs (ubuntu control panel, system settings), but not e.g. in banshee, the top part of the window contains elements in dark tone (with the Ambience theme). But I cant find a standard widget that does this automatically.

Are these colors all set by hand (instead of standard widget+theme)? And if they are set by hand, where do they come from in the theme (what are the parameters in gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &color)) ?

EDIT: It does not seem to be a simple Gtk.Toolbar. If I run the following code:

from gi.repository import Gtk
window = Gtk.Window()
window.set_default_size(200, -1)
window.connect("destroy", lambda q: Gtk.main_quit())
toolbar = Gtk.Toolbar()
window.add(toolbar)
toolbutton = Gtk.ToolButton(stock_id=Gtk.STOCK_NEW)
toolbar.add(toolbutton)
window.show_all()
Gtk.main()

I get a window like this: enter image description here which does not have a dark tone for the toolbar.

EDIT2: Although the 'toolbar with special context' answer by j-johan-edwards is true in most of the programs, it is not the case in the ubuntuone-control-panel. This program has a GtkVBox which can include any range of widgets (unlike a toolbar). I'm still unable to determine how the gtk-theme knows how to paint that part of the window. enter image description here

But anyway: for now a toolbar is enough for me...


Solution 1:

Do you mean these?

GTK3 Toolbar

They're just Gtk.Toolbars. The reason some applications like Banshee don't use them is that they haven't yet ported to GTK+ 3, and received the new theming capabilities that enable toolbars like that.

To port your own Python application to GTK+ 3, you need to use PyGObject instead of PyGTK. As of 12.04, Quickly will generate PyGObject projects by default.

You also need to add primary-toolbar to the toolbar style context. Like so:

toolbar = Gtk.Toolbar()
context = toolbar.get_style_context()
context.add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)

applying that context to the question example results in this:

demo

Solution 2:

With regards to the second part of your question, which was "How to add VBox to the toolbar", all you have to do is wrap it inside a Gtk.ToolItem, eg:.

...
self.toolbar = Gtk.Toolbar()
self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
tool_item = Gtk.ToolItem()
tool_item.add(self.box)
self.toolbar.insert(tool_item, 0)
...

You can make it simpler by creating a helper function or extending Gtk.Toolbar, for example:

custom_toolbar.py

from gi.repository import Gtk

class CustomToolbar(Gtk.Toolbar):
    def __init__(self):
        super(CustomToolbar, self).__init__()
        ''' Set toolbar style '''
        context = self.get_style_context()
        context.add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)

    def insert(self, item, pos):
        ''' If widget is not an instance of Gtk.ToolItem then wrap it inside one '''
        if not isinstance(item, Gtk.ToolItem):
            widget = Gtk.ToolItem()
            widget.add(item)
            item = widget

        super(CustomToolbar, self).insert(item, pos)
        return item

It simply checks if the object you try to insert is a ToolItem, and if not, it wraps it inside one. Usage example:

main.py

#!/usr/bin/python
from gi.repository import Gtk
from custom_toolbar import CustomToolbar

class MySongPlayerWindow(Gtk.Window):
    def __init__(self):
        super(MySongPlayerWindow, self).__init__(title="My Song Player")
        self.set_size_request(640, 480)

        layout = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.add(layout)

        status_bar = Gtk.Statusbar()
        layout.pack_end(status_bar, False, True, 0)

        big_button = Gtk.Button(label="Play music")
        layout.pack_end(big_button, True, True, 0)

        ''' Create a custom toolbar '''
        toolbar = CustomToolbar()
        toolbar.set_style(Gtk.ToolbarStyle.BOTH)        
        layout.pack_start(toolbar, False, True, 0)

        ''' Add some standard toolbar buttons '''
        play_button = Gtk.ToggleToolButton(stock_id=Gtk.STOCK_MEDIA_PLAY)
        toolbar.insert(play_button, -1)

        stop_button = Gtk.ToolButton(stock_id=Gtk.STOCK_MEDIA_STOP)
        toolbar.insert(stop_button, -1)

        ''' Create a vertical box '''
        playback_info = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, margin_top=5, margin_bottom=5, margin_left=10, margin_right=10)

        ''' Add some children... '''
        label_current_song = Gtk.Label(label="Artist - Song Name", margin_bottom=5)
        playback_info.pack_start(label_current_song, True, True, 0)

        playback_progress = Gtk.ProgressBar(fraction=0.6)
        playback_info.pack_start(playback_progress, True, True, 0)

        '''
        Add the vertical box to the toolbar. Please note, that unlike Gtk.Toolbar.insert,
        CustomToolbar.insert returns a ToolItem instance that we can manipulate
        '''
        playback_info_item = toolbar.insert(playback_info, -1)
        playback_info_item.set_expand(True)        

        ''' Add another custom item '''       
        search_entry = Gtk.Entry(text='Search')
        search_item = toolbar.insert(search_entry, -1)
        search_item.set_vexpand(False)
        search_item.set_valign(Gtk.Align.CENTER)

win = MySongPlayerWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()

It should look like this