Notebookbar, or tabbed interface is an attempt to modernize LibreOffice user interface. In these series, I try to explain the implementation in LibreOffice code. In the first part, I discuss custom Glade widgets that are building blocks of Notebookbar user interface.
Building LibreOffice From Sources
If you haven’t built LibreOffice from sources before, you can refer to can refer to this tutorial:
The next sections assume that you have a working build environment.
Custom Widgets in Glade Catalogs
Notebookbar implementation consists of .ui files, configuration files and C++ implementation. Let’s look into the user interface files.
First time that you clone LibreOffice source code, and try to open a Notebookbar UI file like this, you may see error:
$ glade ./sc/uiconfig/scalc/ui/notebookbar.ui
You may see an error, which indicates that a required catalog related to LibreOffice is not available.
To fix this issue, you have to know that Notebookbar uses custom widgets that with the Glade interface designer. These custom widgets are available from a Glade catalog with the name of LibreOffice.
Inside sc/uiconfig/scalc/ui/notebookbar.ui
, you may see these two lines:
<requires lib="gtk+" version="3.20"/> <requires lib="LibreOffice" version="1.0"/>
Glade catalogs are xml files with the keyword glade-catalog inside them, so we can search for this keyword:
$ git grep -l glade-catalog extras/source/glade/libreoffice-catalog.xml.in extras/source/glade/makewidgetgroup.xslt
The .in files is an input file in which the build process creates the final xml file out of it. Searching for glade-catalog inside the build folder results:
$ grep -lr glade-catalog ... instdir/share/glade/libreoffice-catalog.xml
As you can see, the result goes inside the folder instdir/share/glade/
, so to be able to use the catalog, you should add this folder to the glade catalog search path. One of the easiest ways to do this, is to add it via Glade interface itself. Use ☰ (hamburger menu), go to “Glade Preferences”, and add instdir/share/glade/
to the “Extra Catalog & Template paths”. Then, reload a notebookbar UI file, and the error should go away. This setting is saved inside ~/.config/glade.conf
configuration file.
Custom Widgets for the Notebookbar
Inside the Glade custom catalog instdir/share/glade/libreoffice-catalog.xml
, you can see 10 custom widgets:
$ grep "glade-widget-class\ " instdir/share/glade/libreoffice-catalog.xml <glade-widget-class title="Notebookbar ToolBox" name="sfxlo-NotebookbarToolBox" generic-name="Notebookbar ToolBox" parent="GtkToolbar" icon-name="widget-gtk-toolbar"> <glade-widget-class title="Notebook switching tabs depending on context" name="sfxlo-NotebookbarTabControl" generic-name="NotebookbarTabControl" parent="GtkNotebook" icon-name="widget-gtk-notebook"/> <glade-widget-class title="Horizontal box hiding children depending on its priorities" name="sfxlo-PriorityHBox" generic-name="PriorityHBox" parent="GtkBox" icon-name="widget-gtk-box"/> <glade-widget-class title="Horizontal box hiding children depending on its priorities" name="sfxlo-PriorityMergedHBox" generic-name="PriorityMergedHBox" parent="GtkBox" icon-name="widget-gtk-box"/> <glade-widget-class title="Box which can move own content to the popup" name="sfxlo-DropdownBox" generic-name="DropdownBox" parent="GtkBox" icon-name="widget-gtk-box"/> <glade-widget-class title="Box which can hide own content" name="VclOptionalBox" generic-name="VclOptionalBox" parent="GtkBox" icon-name="widget-gtk-box"/> <glade-widget-class title="Vertical box hiding children depending on context" name="sfxlo-ContextVBox" generic-name="ContextVBox" parent="GtkBox" icon-name="widget-gtk-box"/> <glade-widget-class title="Managed Menu Button" name="svtlo-ManagedMenuButton" generic-name="ManagedMenuButton" parent="GtkButton" icon-name="widget-gtk-button"/> <glade-widget-class title="NotebookBar Toolbar Addons" name="NotebookBarAddonsToolMergePoint" generic-name="ShowText" parent="GtkToolButton" icon-name="widget-gtk-toolbutton"/> <glade-widget-class title="NotebookBar MenuItem Addons" name="NotebookBarAddonsMenuMergePoint" generic-name="ShowText" parent="GtkMenuItem" icon-name="widget-gtk-menuitem"/>
The previous xml shows the custom widgets that are building blocks of building Notebookbar. Let’s look into each of them, based on their title and names.
In the next picture, you can see the notebookbar in LibreOffice, and compare it to what is visible in Glade user interface designer. As you can see, not everything is visible in the designer. Specifically, icons and text are not visible in the designer but are visible in the final application.
Main Widget
1. Notebookbar Tab Control: This widget has the name sfxlo-NotebookbarTabControl
, and is the primary widget for Notebookbar. It can change the set of visible tabs based on the user context. Its parent class is GtkNotebook
and provides context-sensitive tab switching.
Container Widgets
2. NotebookbarToolBox: This widget is named sfxlo-NotebookbarToolBox
, its parent class is GtkToolbar
. It can contain toolbar elements.
3. Priority Horizontal Box: This widget has the name sfxlo-PriorityHBox
, and its parent class is GtkBox
. It is the horizontal box hiding children depending on its priorities. In this way, lower priority widgets becomes hidden to give the more important widgets room to be displayed on a screen that is not big enough to show all the available elements.
4. Priority Merged Horizontal Box: This widget has the name sfxlo-PriorityMergedHBox
, and its parent class is GtkBox
. It is the “horizontal box hiding children depending on its priorities”. This widget is also related to the previous one for creating more room for important widgets, but it is used inside the PriorityHBox
.
5. Optional Box: This widget has the name VclOptionalBox
, and its parent class is GtkBox
. This “box which can hide own content”, is a widget that is useful for creating small areas dedicated to a specific purpose. For example, you may see Home-Section-Clipboard
, which is used to define an area for clipboard related tasks inside Home tab.
6. Contextual Vertical Box: This widget has the name sfxlo-ContextVBox
and is a “vertical box hiding children depending on context” and its parent class is GtkBox
. It provides a box that can act based on the context, showing and hiding its children accordingly. You may look into sw/uiconfig/swriter/ui/notebookbar_single.ui
, which provides an example use.
Here is the correct control hierarchy, as depicted and described in the TDF Wiki:
Menu Widgets
7. Dropdown Box: This widget has the name sfxlo-DropdownBox
, its parent class is GtkBox
and is a “box which can move own content to the popup”. This is also useful where the space for the tabbed interface is not big enough. The menu, is what you can see in “File” and “Help” menu in every notebookbar in LibreOffice tabbed interface. Please note that only 1 GtkBox child should be inside it, so that the popup works properly. In fact, the above diagram shows the correct usage.
8. Managed Menu Button: This widget has the name svtlo-ManagedMenuButton
, and its parent class is GtkButton
. It is a “Managed Menu Button”. It provides a button that opens a dynamic menu which is populated according to the context.
Custom Widgets for the Extensions
9. NotebookBar MenuItem Addons: This widget has the name NotebookBarAddonsToolMergePoint
, and its parent class is GtkToolButton
. Specifically, LibreOffice extensions can use it for adding additional tools to the notebookbar.
10. NotebookBar MenuItem Addons: This widget has the name NotebookBarAddonsMenuMergePoint
, and its parent class is GtkMenuItem
. This is also used for adding extra items into the notebookbar.
Final Notes
You can find useful information about Notebookbar in the design team blog:
- Easyhacking: How to set up your environment
- DIY UI: How to create your own Notebookbar
- Evolving Past the Restrictions of Toolbars
And at last, these are some useful Wiki articles around Notebookbar in the TDF Wiki: