Rich Text API
This document describes different approaches that can be used by javafx to offer Rich Text support.
The two main options described here are:
In all likelihood, in this style of API the existent Text node would be modified to allow style objects to be applied to ranges of its text content. This design is used by several text layout solution (CoreText, Pango, DirectWrite, SWT, AWT, etc)
This option involves adding new nodes to the scene layer, in particular a new parent node with the capability of grouping several text spans (Text node) and other graphic elements (ImageView, Canvas) and laying them out in a text paragraph following all applicable text layout rules to the entire content (bidi reordering, wrapping, justification, etc). This option is similar to HTML+CSS.
Whichever design is chosen, the following statement should always be true:
Any style that can be applied to text layout using code should also be possible to be described in CSS.
The usage of CSS should not be limited to just the simple case (className/id). It should, as much as possible, allow for any css selectors (including those based on node relationship).
For reference, the following are the different ways a node can be styled in javafx:
Adding class name
Setting inline style
Setting property directly
This section presents a few different use cases with a possible implementation and discussion using the options described above.
Simple case, make one word bold
Sample text: Hello Bold World.
New APIs added:
int start - inclusive start offset
int end - exclusive end offset
TextStyle style - the style to be applied to the range.
new class TextStyle
- Text#setStyle merges new style with existent styles (by overwritten them)
- start,end could be moved to TextStyle but that would make TextStyle not reusable
- TextStyle: does it need to support all the styling methods available to node (see #table)?
- does it need TextStyle.setFont(), setUnderline(), setWhatever() ?
- does it need TextStyle.setStyle() (in the same form as Node.setStyle()) ?
An alternative is a dictionary style API:
TextStyle.addStyle("-fx-font", "12pt bold system");
This is similar to other system:
For example, Apple CoreText a CFAttributedString is a combination of the CFDictionary and a CFString.
node.style.FxFont = "12pt bold System";
node.style["FxFont"] = "12pt bold System";
In addition, the option to set a class name and id should for a TextStyle should be available:
Embed image in a text
Sample text: HelloWorld.
- This case can't be expressed using CSS with an Attributed String API
- Image is vertically aligned at the bottom of the text layout
Use CSS selectors to implement theming
Suppose we are implementing a code editor, code has different token (keywords, literal, comments), each token as a style (described in the stylesheet).
The editor has to support theme, which means that at anytime a new theme can be set and the style for the tokens replaced.
Sample text: public String name = "Joe";
In HTML, that can be display with:
There is eclipse.css with the content:
The way this works is, for example, if there is node with the "keyword" class which is a descent of a node with the "eclipse" class then apply the purple bold style.
Now assume that a new netbeans.css is added:
document.getElementById("editor").className = "netbeans";
and everything works.
Note that the eclipse.css does not need to be removed. In fact, all stylesheets can be loaded at startup time (which is usual in HTML).
The span node with content equals to "public" always has the "keyword" class name, but it is no longer a descent of a node with the class name of "eclipse", which means the purple bold style does not apply to it anymore. It is now a descent of a node with the class name "netbeans" and as such it will have the style blue applied to it.
With a DOM Style API this type of situation can be solved the same way it is done in HTML.
With an Attributed String API this will have to be done by hand, adding and removing styles one by one everywhere in the scene graph.