Interface SwingTreeStyledComponentUI<C extends JComponent>

Type Parameters:
C - The type of JComponent for which a particular ComponentUI is designed.

public interface SwingTreeStyledComponentUI<C extends JComponent>
This interface is intended to be implemented by the various 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: The third major way of styling is through the 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:

  1. Gathering style information to the SwingTree style engine by invoking the style(ComponentStyleDelegate) implementation.
  2. Checking if canForwardPaintingToSwingTree() returns true and then expecting the ComponentUI.paint(Graphics, JComponent) to delegate to SwingTrees ComponentExtension.paintBackground(Graphics, swingtree.api.Painter) method.
When SwingTree resolves a style, it will detect that the 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:

  1. Global Defaults - (see StyleSheet)
  2. Component Look and Feel - (this SwingTreeStyledComponentUI)
  3. Component Declaration - (see UIForAnySwing.withStyle(Styler))
In other words:
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 Details

    • installUI

      void installUI(JComponent c)
      This method must be implemented through ComponentUI.installUI(JComponent)! It configures the specified component appropriately for a SwingTree compatible look and feel. This method is invoked when the ComponentUI instance 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:
      1. 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.
      2. Install a LayoutManager on the component if necessary.
      3. Create/add any required subcomponents to the component.
      4. Create/install event listeners on the component.
      5. Create/install a PropertyChangeListener on the component in order to detect and respond to component property changes appropriately.
      6. Install keyboard UI (mnemonics, traversal, etc.) on the component.
      7. Initialize any appropriate instance data.

      IMPORTANT:
      For full SwingTree interoperability, implementations of this should invoke ComponentExtension.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

      void paint(Graphics g, JComponent c)
      This method must be implemented through ComponentUI.paint(Graphics, JComponent)! It paints the specified component appropriately for the look and feel. This method is invoked from the ComponentUI.update(Graphics, JComponent) method when the specified component is being painted. Subclasses should override this method and use the specified Graphics object to render the content of the component.
      For full SwingTree interoperability, you should override canForwardPaintingToSwingTree() to return true and 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 - the Graphics context in which to paint
      c - 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 a ComponentStyleDelegate and applies style information to it by transforming it to a new ComponentStyleDelegate.
      This styling will happen after/on-top of the style supplied by a StyleSheet but it will happen before the style directly declared for a specific component instance using the UIForAnySwing.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 - The ComponentStyleDelegate to apply the style to.
      Returns:
      A new ComponentStyleDelegate that 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 forward ComponentUI.paint(Graphics, JComponent) and ComponentUI.update(Graphics, JComponent) draw calls to SwingTrees's ComponentExtension.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 return true. This will turn your ComponentUI implementation 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 returns true, but the ComponentUI.paint(Graphics, JComponent) implementation does NOT delegate to ComponentExtension.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.