27.5. Custom renderers and renderer factories

It is always the responsibility of the extension point to render an action. The need for custom renderers is typically very small, at least if you want your extensions to blend into the look and feel of the BASE web client. Most customizations can be probably be handled by stylesheets and images. That said, you may still have a reason for using a custom renderer.

Renderer factories are not very different from action factories. They are specified in the same way in the XML file and uses the same method for initialisation, including support for path conversion, etc. The difference is that you use a <renderer-factory> tag instead of an <action-factory> tag.


<renderer-factory>
   <factory-class>
      ... some factory class ...
   </factory-class>
   <parameters>
      ... some parameters ...
   </parameters>
</renderer-factory>

A RendererFactory also has a prepareContext() method that can be used to tell the web client about any scripts or stylesheets the extension needs. If your renderer factory extends the AbstractJspRendererFactory class you will not have to worry about this since you can configure scripts and stylesheets in the XML file.

A render factory must also implement the getRenderer() which should return a Renderer instance. The extension system will then call the Renderer.render() method to render an action. This method may be called multiple times if the extension created more than one action.

The renderers responsibility is to generate the HTML that is going to be sent to the web client. To do this it needs access to the JspContext object that was passed to the renderer factory. Here is a simple outline of both a renderer factory and renderer.


// File: MyRendererFactory.java
public class MyRendererFactory
   extends AbstractJspRendererFactory<MyAction>
{

   public MyRendererFactory()
   {}

   @Override
   public MyRenderer getRenderer(InvokationContext context)
   {
      return new MyRenderer((JspContext)context.getClientContext());
   }
}

// File: MyRenderer.java
public class MyRenderer
   implements Renderer<MyAction>
{

   private final JspContext context;
   public MyRenderer(JspContext context)
   {
      this.context = context;
   }

   /**
      Generates HTML (unless invisible): 
      <a class="[clazz]" style="[style]" href="[href]">[title]</a>
   */
   public void render(MyAction action)
   {
      if (!action.isVisible()) return;
      Writer out = context.getOut();
      try
      {
         out.write("<a");
         if (action.getClazz() != null) 
         {
            out.write(" class=\"" + action.getClazz() + "\"");
         }
         if (action.getStyle() != null) 
         {
            out.write(" style=\"" + action.getStyle() + "\"");
         }
         if (action.getHref() != null) 
         {
            out.write(" href=\"" + action.getHref() + "\"");
         }
         out.write(">");
         out.write(HTML.encodeTags(action.getTitle()));
         out.write("</a>\n");
      }
      catch (IOException ex)
      {
         throw new RuntimeException(ex);
      }
   }
}