Interface SwingTreeStyledComponentUI<C extends JComponent>
- Type Parameters:
C- The type ofJComponentfor which a particularComponentUIis designed.
ComponentUI extensions
of a custom Look and Feel which desires to fully integrate with the SwingTree style engine.For context, it is important to note that SwingTree ships with a rich style rendering engine and three main ways for configuring styles.
The most prominent once, which are typically used to build an application, are:
-
Global Styling:
see
StyleSheet,UIFactoryMethods.use(StyleSheet, Supplier),SwingTree.initializeUsing(SwingTreeConfigurator) -
Direct Styling in the GUI:
seeUIForAnySwing.withStyle(Styler)
alsoUIForAnySwing.withTransitionalStyle(Val, LifeTime, AnimatedStyler)
andUIForAnySwing.withTransitoryStyle(Observable, LifeTime, AnimatedStyler)
ComponentUI
of a custom Look and Feel implementing this marker interface SwingTreeStyledComponentUI.
So if you develop your own Look and Feel, then you can make it compatible with SwingTree by having your
ComponentUI extensions implement this SwingTreeStyledComponentUI interface.
SwingTree will cooperate with the ComponentUI in two major ways:
-
Gathering style information to the SwingTree style engine
by invoking the
style(ComponentStyleDelegate)implementation. -
Checking if
canForwardPaintingToSwingTree()returnstrueand then expecting theComponentUI.paint(Graphics, JComponent)to delegate to SwingTreesComponentExtension.paintBackground(Graphics, swingtree.api.Painter)method.
ComponentUI
of a particular JComponent implements this interface, and then invoke the
style(ComponentStyleDelegate) method to gather style information.That way a custom look and feel can delegate the complex rendering directly to the SwingTree style engine. You as Look and Feel developer can thereby focus on writing code which conveys the intent of how a particular type of component ought to look like much more clearly.
Note that the order in which a renderable style is computed in SwingTree follows the following order:
- Global Defaults - (see
StyleSheet) - Component Look and Feel - (this
SwingTreeStyledComponentUI) - Component Declaration - (see
UIForAnySwing.withStyle(Styler))
A
ComponentStyleDelegate will be sent through
a StyleSheet, then it will go through this SwingTreeStyledComponentUI
and finally UIForAnySwing.withStyle(Styler) on a concrete component.
But for full interoperability you may also want to have canForwardPaintingToSwingTree()
always return true, and then implement ComponentUI.paint(Graphics, JComponent)
to delegate to SwingTree like so:
@Override
public void paint(
Graphics g,
JComponent comp
) {
ComponentExtension.from(comp)
.paintBackground(g, g2d->{
super.paint(g2d, comp);
});
}
@Override
public boolean canForwardPaintingToSwingTree() {
return true;
}
That way, the SwingTrees style engine works reliably for all components!-
Method Summary
Modifier and TypeMethodDescriptiondefault booleanIf you want to achieve full compatibility and interoperability with SwingTree in your Look and Feel you have to forwardComponentUI.paint(Graphics, JComponent)andComponentUI.update(Graphics, JComponent)draw calls to SwingTrees'sComponentExtension.paintBackground(Graphics, swingtree.api.Painter)method! To inform SwingTree that you are going to do this, you also have to override this method and make it returntrue.voidThis method must be implemented throughComponentUI.installUI(JComponent)! It configures the specified component appropriately for a SwingTree compatible look and feel.voidpaint(Graphics g, JComponent c) This method must be implemented throughComponentUI.paint(Graphics, JComponent)! It paints the specified component appropriately for the look and feel.style(ComponentStyleDelegate<C> delegate) Receives aComponentStyleDelegateand applies style information to it by transforming it to a newComponentStyleDelegate.
-
Method Details
-
installUI
This method must be implemented throughComponentUI.installUI(JComponent)! It configures the specified component appropriately for a SwingTree compatible look and feel. This method is invoked when theComponentUIinstance is being installed as the UI delegate on the specified component. This method should completely configure the component for the look and feel, including the following:- Install default property values for color, fonts, borders, icons, opacity, etc. on the component. Whenever possible, property values initialized by the client program should not be overridden.
- Install a
LayoutManageron the component if necessary. - Create/add any required subcomponents to the component.
- Create/install event listeners on the component.
- Create/install a
PropertyChangeListeneron the component in order to detect and respond to component property changes appropriately. - Install keyboard UI (mnemonics, traversal, etc.) on the component.
- Initialize any appropriate instance data.
IMPORTANT:
For full SwingTree interoperability, implementations of this should invokeComponentExtension.gatherApplyAndInstallStyle(boolean)to ensure that the SwingTree style of a particular component is installed correctly.
So an implementation may look something like this:// Override public void installUI( JComponent comp ) { ComponentExtension.from(comp) .gatherApplyAndInstallStyle(true); }- Parameters:
c- the component where this UI delegate is being installed- See Also:
-
paint
This method must be implemented throughComponentUI.paint(Graphics, JComponent)! It paints the specified component appropriately for the look and feel. This method is invoked from theComponentUI.update(Graphics, JComponent)method when the specified component is being painted. Subclasses should override this method and use the specifiedGraphicsobject to render the content of the component.
For full SwingTree interoperability, you should overridecanForwardPaintingToSwingTree()to returntrueand then forward the paint request to SwingTree like so:// Override public void paint( Graphics g, JComponent comp ) { ComponentExtension.from(comp) .paintBackground(g, g2d->{ super.paint(g2d, comp); }); }- Parameters:
g- theGraphicscontext in which to paintc- the component being painted; this argument is often ignored, but might be used if the UI object is stateless and shared by multiple components- See Also:
-
style
Receives aComponentStyleDelegateand applies style information to it by transforming it to a newComponentStyleDelegate.
This styling will happen after/on-top of the style supplied by aStyleSheetbut it will happen before the style directly declared for a specific component instance using theUIForAnySwing.withStyle(Styler)method.
Note that this method is designed to only be invoked by SwingTree internal code. You should never invoke it yourself.- Parameters:
delegate- TheComponentStyleDelegateto apply the style to.- Returns:
- A new
ComponentStyleDelegatethat has the style applied. - Throws:
Exception- if the style could not be applied by the client code.
-
canForwardPaintingToSwingTree
default boolean canForwardPaintingToSwingTree()If you want to achieve full compatibility and interoperability with SwingTree in your Look and Feel you have to forwardComponentUI.paint(Graphics, JComponent)andComponentUI.update(Graphics, JComponent)draw calls to SwingTrees'sComponentExtension.paintBackground(Graphics, swingtree.api.Painter)method! To inform SwingTree that you are going to do this, you also have to override this method and make it returntrue. This will turn yourComponentUIimplementation into the main way in which SwingTree renders its style onto a specific component type.
So your implementation would look something like this:// Override public void paint( Graphics g, JComponent comp ) { ComponentExtension.from(comp) .paintBackground(g, g2d->{ super.paint(g2d, comp); }); } // Override public boolean canForwardPaintingToSwingTree() { return true; }WARNING:
If this method returnstrue, but theComponentUI.paint(Graphics, JComponent)implementation does NOT delegate toComponentExtension.paintBackground(Graphics, swingtree.api.Painter), then you will effectively break the style rendering of your components!
This is because in that case, SwingTree relies entirely on your override to be the sole way of hooking into Swings component rendering.- Returns:
- A flag which informs SwingTree if it can rely on your
ComponentUI.paint(Graphics, JComponent)implementation to be used for hooking its style engine into the rendering pipeline of a component.
-