VCL UI Rework
Contents
- 1 Rational
- 2 Requirements
- 3 Ongoing work
Rational
Currently all dialogs (along with most translated strings) are stored in a rather unusual binary resource file format, that has not had much love in the last decade. We need to write some new code that separates the process of designing & laying out the UI from the code - to allow UE to make our UI more beautiful, and allow future re-factoring. The existing Basic GUI dialog editor and it's XML format should be re-used, a simple C++ compatibility API created, and a number of dialogs converted to the new format.
Requirements
There have already been several attempts at adding features to VCL, and of course people have different requirements, an initial synthesis of requirements is perhaps helpful. Please do add subsequent constraints, or comments thereof.
Simple code changes (Mandatory)
Of course, we want to remove lots of code - all the immediate construction of non-core widgets that do not require special handling for a start. However - given the scope of the problem, it does not seem sensible to require some vast re-writing of each & every dialog from day 1. ie. re-implementing all callbacks using a UNO Listener type interface would kill the task, we should stick with existing callback mechanisms and signatures.
QA Test tool (Mandatory)
We need to ensure either, that relevant qa testtool tests are updated to use the new UI code, or that we have a strong back-compat story here.
Re-use of existing code (Desirable)
Clearly the existing form code has not only a working XML serialization, but code to (re)store from that, re-using that where at all possible is important. Unfortunately this code is rather complex and difficult to work with. A life-boat approach to creating a new cleaner, smaller structure and moving dialogs across would perhaps be better.
Simple new APIs (Important)
The existing & successful [libglade API] is a good model to build from. Identifying widgets and signals by strings seems to scale well and be more extensible than the SID based system.
I18n (Important)
The i18n story is important, quite possibly we'll want to process any Form XML to introduce integer IDs to identify strings, feature creep into re-writing i18n might kill this project.
Layout (Mandatory)
Adding automatic layout, as modern toolkits do, would substantially help improve the look of the UI, it's portability to other platforms, and also it's look when translated.
Support for platform specific layout and HIG
The UI layouting mechanism should (where possible) automatically adapt the XML UI description to the conventions of the platform.
For changes that are beyond possibilities of automatic layout, there should be a possibility to add conditional UI layout that allows to use different XML descriptions for different platforms (only specific sub-areas of a dialog/whatever, preferably not the whole dialog).
- Example 1: The typical "OK" and "Cancel" -buttons in a dialog are
- WINDOWS: "OK" (first), "Cancel" (second), both aligned to the right bottom edge of the dialog.
- LINUX (QT): same as Windows, except that Apply goes between OK and Cancel if present
- MAC OS X: The OK button sits in the lower right corner, the cancel button left to it and then all other buttons. An optional HelpButton follows a completely different look (it is a small icon with a questionmark basically). For more Mac OS X examples, see Mac OS Porter Team at WWDC 2007
- LINUX (GTK): same as Mac OS X, except that Help has both an icon and text
- Example 2: Preferences dialogs
- WINDOWS: This type of dialogs are called "Options" and are under the Tools menu. There is typically "OK" and "Cancel" -buttons, in that order.
- LINUX (GTK): This type of dialogs are called "Preferences" and are under the Edit menu. There is typically "Help" (optional) and "Close" -buttons, in that order. The dialog instantly applies any changes.
- LINUX (KDE only): This type of dialogs are called "Configure ($APP_NAME|Toolbars|Shortcuts)…" and are under the Settings menu.
- MAC OS X: This type of dialogs are called "Preferences", there are no regular buttons, optionally just a circular "?" -button for help. The dialog instantly applies any changes, and can be closed from the window border's red circular button (upper left corner). The menu item is found under the $APP_NAME menu.
- Example 3: Changing values related to currently selected object in document
- WINDOWS: Relatively many icons/widgets in several toolbars, some context sensitive toolbars exist, but they are specific to certain object types.
- LINUX (GTK): Usually 1 to 2 static toolbars with 10-25 widgets each. For contextual actions, either one ever-changing toolbar with an assortment of widgets similar to Office 2007's (example: Inkscape) or a Properties dockable pane similar to the Inspector on Mac (example: Glade).
- MAC OS X: In addition to one main toolbar with about 6-12 user-configurable (drag-n-drop) icons (= big buttons with text underneath), there is a separate "Inspector" widget for changing values related to the currently selected object in the document. Selecting a different object, changes the contents of the inspector widget, it does not open a new toolbar. If there are many settings, they can be divided into tab-pages within the inspector.
Reduced Inheritance (Desirable)
Currently all dialogs inherit (somehow) from VCL's Window class. Such inheritance from virtual bases generates large vtables, and substantial inefficiency across the code-base. Wherever possible we should have a child instance of the relevant window & use an aggregating pattern. In other cases, we may want to have a simple base class to inherit from with 'Show' / 'Hide' type methods that chain to the aggregated instance, and in more complex situations stick with an inherited approach.
It would also be good to do some code size profiles of the resulting code, to optimise for reduced code size.
New file format (Desirable)
Deprecating the rsc code, and preferably removing it is a good goal. There is a decision to be made whether the layout information is mangled with the widgets or defined alongside.
- Having layout information and widgets mixed like in XUL
- pro: format is more human readable in an XML editor
- con: current implementation to read/store the widgets from/to XML must be altered
- Having layout information and widgets separated in one or more XML files
- pro: format may be easier to use by a dialog editor (see NetBeans GUI Editor using javax.swing.GroupLayout
- pro: implementation is faster as it must not be implemented inside the existing XML code for widgets (better compatibility, lower risk of regressions)
- con: not as easy to edit for humans in an XML editor
Easy to use Dialog Editor (Desirable)
To allow User Experience to tweak the UI easily, it is necessary to implement an easy-to-use GUI editor that allows the UI to be tweaked simply.
- NetBeans has an interactive GUI editor that also supports layouts. Quickstart Guide
Ongoing work
Phases of the work:
- Implement layout / container implementations
- Implement new, simple, hierarchical XML serialization of widgets & layout
- Implement helper API & port sample dialogs
- Implement resource file encapsulation
- Implement support in dialog editor in basctl (optional)
- Commence porting dialogs
layout / container implementations *prototype complete*
Several prototypes out there to choose from. Various decisions
- as little new API as possible - use introspectable / self describing 'child' properties
- only the basic box, table and alignment primitives necessary to start with
new XML format *skeleton complete*
This is based on the widget hierarchy, property and child property names, suitable mangled. The layout information is included in-line with the widgets, to avoid indirection related complexity.
helper API *commenced*
In order to reduce code impact, we should incrementally create thin wrapper api around the AWT UNO APIs, providing VCL-like back-compatibility logic, to substantially limit the scope of the code changes. We should provide 'placeholders' whereby complex widgets can easily be inserted into the layout & used as-before.
We should port at least 3 sample dialogs (~1 done so far)
resource file
The resource file format can re-use the package code for a .zip encapsulation, though some tweaks will be necessary to populate an existing dialog parent with widgets, for those widgets that are re-used elsewhere.
support in dialog editor
This will require more GUI work, extending the palette and adding properties specific to layout containers.
i18n
- mark i18n attributes by prepending an underscore: <radiobutton id="RB1" _label="One"/>
- implement new transex3 tool to extract strings from template XML into ubiquitous localize.sdf files and produce i18n tree of translated XMLs at compile time
- use simple read-right translation
- eventually read XMLs from per-language zip files: share/layout/de.zip, share/layout/nl.zip etc.
.src converter
The process of converting 360,000+ lines of .src file to XML is a fairly daunting one. This is where Kohei's src2xml converter can help.
The src2xml tool currently will convert:
ModalDialog RID_SVXDLG_ZOOM { HelpId = SID_ATTR_ZOOM ; OutputSize = TRUE ; SvLook = TRUE ; Size = MAP_APPFONT ( 202 , 116 ) ; Moveable = TRUE ; FixedLine FL_ZOOM { Pos = MAP_APPFONT ( 6 , 3 ) ; Size = MAP_APPFONT ( 92 , 8 ) ; Text [ en-US ] = "Zoom factor"; }; RadioButton BTN_OPTIMAL { Pos = MAP_APPFONT ( 12 , 15 ) ; Size = MAP_APPFONT ( 80 , 10 ) ; Text [ en-US ] = "~Optimal" ; }; }
into:
<?xml version="1.0" encoding="UTF-8"?> <modaldialog "sizeable=true" help-id="SID_ATTR_ZOOM" moveable="true" output-size="true" id="RID_SVXDLG_ZOOM" sv-look="true" xmlns="http://openoffice.org/2007/layout" xmlns:cnt="http://openoffice.org/2007/layout/container"> <vbox> <fixedline id="FL_ZOOM" _text="Zoom factor"/> <radiobutton id="BTN_OPTIMAL" _text="~Optimal"/> </vbox> </modaldialog>
ie. just whacks all the widgets into a single vbox, to allow later layout work to be done by hand / in the GUI editor.
Dialog Editor
This should be written using our VCL-like wrapper API wherever possible - as a means to extend & mature the wrapper API itself. The code should be hosted in our 'test' application initially (due to evil UNO bootstrapping problems to horrible to detail). Steps:
- introspect the layout hierarchy, and write out the containers and all their properties as XML. This would currently be stymied by the lack of interface capabilities to introspect children; thus adding a method
sequence<XLayoutConstrains> getChildren()
tolayout/source/api/com/sun/star/awt/XInterfaceContainer
would be rather helpful. - a palette should be created added, and widget selection & creation allowed
- requires construction of a 'placeholder' widget to reserve space for adding new widgets.
- icons can be re-used from existing OO.o toolbars for this.
- we should present properties (initially) generically
- ie. by introspection determine a properties' type and hence what kind of control to present.
- partitioning of child properties & widget properties would also be useful perhaps.
glade2, or stetic gives a good model of how this can be done. A high level of polish is not required.
toolkit/ fixing
The toolkit code is fairly incomplete & curious in it's implementation; we need to extend it where necessary to provide a high behavioral fidelity as we switch from wrapper API to UNO awt to VCL and back.
QA test tool
An audit of qatesttool interaction with dialogs needs to be done, to identify entry points, and resource identification. If necessary the wrapper API & awt needs to propagate 'SmartIds' (or some other identifiers) through to the VCL widgets.