Creating a HIG Toolbar
Making a GNOME HIG compliant toolbar is very simple. First we'll cover how to make the toolbar react to toolbar style and then the detachable state.
Toolbar Style
class ToolbarStyleMonitor (object):
Style = {
"both": gtk.TOOLBAR_BOTH,
"both-horiz": gtk.TOOLBAR_BOTH_HORIZ,
"icons": gtk.TOOLBAR_ICONS,
"text": gtk.TOOLBAR_TEXT
}
def __init__ (self, toolbar):
self.toolbar = toolbar
# Toolbar style
self.__style = gaw.GConfValue (
key = "/desktop/gnome/interface/toolbar_style",
data_spec = gaw.Spec.STRING,
)
self.__style.set_callback (self.__on_style_change)
def style (self):
try:
style = self.__style.data
except:
style = "both"
if style in ToolbarComponent.Style:
return ToolbarComponent.Style[style]
else:
return ToolbarComponent.Style["both"]
style = property (style)
def __on_style_change (self, *args):
self.toolbar.set_style (self.style)
This approach is divided in three steps.
First we get create a
gaw.GConfValue to monitor the key and setup our callback.
The second part is
to know what style is currently being set in the GConf key, so we maintain a
dictionary to establish the relation between the string value and the real
PyGtk constant, when the value is invalid we default to the gtk.TOOLBAR_BOTH
style.
Finally the third part is the style change event, which we simply set
the ToolbarMonitor.style property into the ToolbarMonitor.toolbar
object.
Detachable Toolbar
To create a detachable toolbar one needs three items: a gtk.Toolbar, a gtk.HandleBox and a gtk.VBox. The gtk.HandleBox is used to make the toolbar detachable. The gtk.VBox is used to make it non-detachable. The trick here is to switch the contents of the gtk.VBox, having solely a gtk.Toolbar when we do not want it detachable and having a gtk.HandleBox (whith a gtk.Toolbar inside) to make it detachable.
class ToolbarDetachableMonitor (object):
def __init__ (self, toolbar, handle, wrapper):
self.__detachable = gaw.GConfValue (
key = "/desktop/gnome/interface/toolbar_detachable",
data_spec = gaw.Spec.BOOL
)
self.__detachable.set_callback (self.__on_detachable_change)
self.toolbar = toolbar
self.handle = handle
self.wrapper = wrapper
# Initialize toolbar state
self.__on_detachable_change ()
def __on_detachable_change (self, *args):
widget = self.wrapper.get_children()[0]
if self.detachable:
if widget == self.handle:
return
self.wrapper.remove (widget)
self.wrapper.add (self.handle)
self.handle.add (self.toolbar)
else:
if widget == self.toolbar:
return
self.handle.remove (self.toolbar)
self.wrapper.remove (widget)
self.wrapper.add (self.toolbar)
def detachable (self):
try:
detachable = self.__detachable.data
except:
detachable = False
if not isinstance (detachable, bool):
detachable = False
return detachable
detachable = property (detachable)
Again we've divided our problem into three different parts.
The initialization listens the gaw.GConfValue change event and reacts the
GConf event, it also keeps a reference two our three widgets.
When we change the detachable state we just need to check what's inside the wrapper (the gtk.VBox). If inside the wrapper it's a handle box and we need to change to a non-detachable state then we need to remove the toolbar from the handle box, the handle box from the wrapper and then add the toolbar to the wrapper. If we are in a detachable state and we have a toolbar inside the wrapper then we need to put the toolbar inside the gtk.HandleBox which will reside inside the wrapper. So basically we are switching who contains the toolbar, when we are in detachable state the gtk.HandleBox must contain the toolbar otherwise we just add it to our wrapper.
Finally the detachable state is retrieved from our gaw.GConfValue, we just need
to make sure it's not None.