Skip to:

Tiago Cogumbreiro

O Irrepupável

Back to top

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.


Tags used:

Back to top