JSF 1.2 and h:commandButton custom renderer problem

Hi everyone!
I'm working on my custom h:commandButton renderer for a couple of hours and I cannot solve some issues...
First of all: what I want to do is to substiute default h:commandButton renderer with my own which will call standard renderer and puts some other tags. After all I will have something like that:
    <div class="leftbackground">     
       <div class="rightbackground">
           <input type="button" value="Ok" />  --- this is defaulty rendered by h:commandButton renderer
       </div>
    </div>So that I've put some lines info faces-config.xml:
<render-kit>
         <renderer>
              <component-family>javax.faces.Command</component-family>
              <renderer-type>javax.faces.Button</renderer-type>
              <renderer-class>test.MyCommandButtonRenderer</renderer-class>
         </renderer>
    </render-kit>I've written my own renderer which looks like this:
package test;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.Renderer;
import com.sun.faces.renderkit.html_basic.HtmlBasicRenderer;
public class MyCommandButtonRenderer extends HtmlBasicRenderer{
     public MyCommandButtonRenderer(){
          System.out.println("MyCommandButtonRenderer constructor has been calles");
     public void encodeEnd(FacesContext context, UIComponent component)
               throws IOException {
          try{
          ResponseWriter writer = context.getResponseWriter();
          writer.startElement("h3", component);
          writer.writeText("Hello from a custom JSF UI Component!", null);          
          writer.endElement("h3");  
          }catch(Exception e){
               e.printStackTrace();
}After that, when I try to call h:commandButton on my JSF page:
     <f:view>
          <h:form>
               <h:commandButton  value="Save"  />
          </h:form>
     </f:view>I can see <h3>Hello from a custom JSF UI Component!</h3>. Unfortunately my <input type="button"> isn't rendered.
I have tried something like this:
(in MyCommandRenderer}
public void encodeEnd(FacesContext context, UIComponent component)
               throws IOException {
          try{
          ResponseWriter writer = context.getResponseWriter();
          writer.startElement("h3", component);
          writer.writeText("Hello from a custom JSF UI Component!", null);          
          writer.endElement("h3");  
          String family = "javax.faces.Command";
          String renderType = "javax.faces.Button";
          Renderer baseRenderer =
               context.getRenderKit().getRenderer(family , renderType);
          baseRenderer.encodeEnd(context, component);
          }catch(Exception e){
               e.printStackTrace();
}but it obviously only rendered multiple h3 elements until StackOverflowException is being thrown (it calling himself again and again).
What am I doing wrong? Why my <input type="button"> isn't called? How to call default h:commandButton renderer and told him to render <input type=button> ? Is there any commandButton renderer class I can extend ?Which renderer is used by default by CommandButton component?
Thanks in advance for any help. I'm really close to leave off my work and stay with something more familiar ;)
Sorry for my bad English.
Looking forward to hearing from you,
Matthew
Edited by: MatthewPL on Nov 28, 2007 12:42 AM

To the best of my knowledge, the standard does not specify the default renderer class for any components.
I would take a wrapper/decorator approach. Add a field to your renderer for the default renderer. Before configuring your renderer, obtain the default renderer and set it on your renderer, then configure it.
OTOH, there might be easier ways for you to accomplish what you want to do. You could use a PhaseListener to add components to the view whenever a commandButton is encountered in the tree.

Similar Messages

  • JSF 1.2 and facelets 1.1.11 problems with css

    I've started using facelets to get the templating features - which is working great.
    The problem is that I can't load my css files. The HTML generator converts all of my links into a relative path.
    For example, in my .xhtml file I have this line
    h5. <link rel="stylesheet" type="text/css" href="../../style/themes/smi.css"></link>When it gets to the browser, it becomes this line
    h5. <link href="style/themes/smi.css" rel="stylesheet" type="text/css" />
    Even if I use absolute paths, the compiler converts it to a relative path.
    I've tried adding a <base element, but that just gets removed when the HTML file gets to the browser.

    I'm fairly certain Facelets isn't interested in modified the href attribute of your link tags. I imagine something else is going on here. If you have a simple example, I could try to run it here.
    There was a recent thread on how to use absolute paths in CSS references; I suggest you search the forum for it for tips.

  • JTree custom renderer - JScrollPane

    Hi,
    I am building a JTree and need a custom renderer that will allow me to display the contents of certain leaf nodes in a JEditorPane that is contained in a scrollpane as the leaf may contain a varying amount of text.
    I have managed to get a renderer displaying the text as expected however the scrollbars do not work as I hoped - I cannot scroll down the editorpane.
    Has anyone got an example of a renderer that uses a scrollpane, any help/suggestions would be gratefully received.
    Thanks

    Return the size of your editor pane in customized cell renderer's getPreferredSize() method and set JTree rowHeight to zero. When row height is 0, it use renderer's getPreferredSize() to get size of the cell, I think. I have made custom cellrenderer which extends Jpanel and in getCellRendererComponent I add there another panel which contains buttons etc. I have used super.getPreferredSize() in my renderer's getPreferredSize() method.

  • Question about creating Custom JSF form tag and renderer

    Is it possible to build a custom form tag in JSF and have it replace the standard jsf form tag. Are there any potential issues with child forms or anything else.
    I created the following
    - custom form component class that extends javax.faces.component.UIForm (the only changes I made was to change the value of the COMPONENT_TYPE attribute and change the value for renderer type)
    - custom form renderer class that extends HtmlBasicRenderer and I made changes to the encodebegin method and encrypt the value of the id and action url)
    - custom form tag class that extends UIComponentELTag ( I did not make any changes here)
    - tld for my custom form tag
    - created an entry in faces-config.xml of my web-app for my custom form tag
    Are there any issues with the above.
    Is there something I should do in addition.

    In theory you should be fine. Some of the open source libraries either swap out the renderer for the standard h:form component or supply their own form components. You could look at their code for reference if need be.

  • JSF custom renderer executes multiple times

    I have just created a jsf custom component to render three input texts next to each other (for SSN input). My custom renderer extends javax.faces.render.Renderer, and I am writing out the elements in the encodeEnd method. The problem I encountered is - upon saving the form and the screen refreshes, the renderer gets called two times. So what I end up seeing on the screen are two sets of the three input texts component. Does anyone know why the renderer gets called more than once? Any insight is much appreciated.

    To the best of my knowledge, the standard does not specify the default renderer class for any components.
    I would take a wrapper/decorator approach. Add a field to your renderer for the default renderer. Before configuring your renderer, obtain the default renderer and set it on your renderer, then configure it.
    OTOH, there might be easier ways for you to accomplish what you want to do. You could use a PhaseListener to add components to the view whenever a commandButton is encountered in the tree.

  • JTree selection problem when using custom renderer and editor

    Hello:
    I created a JTree with custom renderer and editor.
    The customization makes JCheckBox to be the component
    responsible for editing and rendering.
    The problem is that when I click on the node with the checkbox
    the JTree selection model does not get updated.
    Without customizations of the editor and renderer the MouseEvent would be fired and BasicTreeUI$MouseHandler.mousePressed() method would call
    the selectPathForEvent() method which would be responsible for updating
    the selection model. At the same time if I attach a mouse listener to the JTree (customized) I see the events when clicking on the nodes. It seems like the MouseEvent gets lost and somehow as a result of which the selection model does not get updated.
    Am I missing something?
    Thanks
    Alexander

    You probably forgot to call super.getTreeCellRendererComponent(...) at the beginning of your getTreeCellRendererComponent(...) method in your custom renderer.
    Or maybe in the getTreeCellEditorComponent(...) of the TreeCellEditor...

  • JSF 1.2 and Tiles integration

    I have a web application using JSF 1.1 and Tiles that I am trying to upgrade to run using JSF 1.2.
    It is working as far as working out that it should use the tile, but then it all seems to fall over when trying to render.
    Does anyone know if it is possible to use Tiles with JSF 1.2?
    Steven

    Hi,
    I took the Shales TileViewHandler and replaced the renderView method with the one below. This is a copy of the method from the Sun RI except that it passes the tile (ComponentDefinition) along to the subsequent methods.
    Then when it gets down to executePageToBuildView the requestURI is obtained from the tile (tile.getPath()) rather than from the UIViewRoot (viewToExecute.getViewId()).
       public void renderView(FacesContext facesContext, UIViewRoot viewToRender)
                                            throws IOException, FacesException {
          String viewId = viewToRender.getViewId();
          String tileName = getTileName(viewId);
          ComponentDefinition tile = getTile(tileName);
          if (log.isDebugEnabled()) {
             String message = null;
             try {
                 message = bundle.getString("tiles.renderingView");
             } catch (MissingResourceException e) {
                 message = "Rendering view {0}, looking for tile {1}";
             synchronized(format) {
                format.applyPattern(message);
                message = format.format(new Object[] { viewId, tileName });
             log.debug(message);
          if (tile != null) {
             if (log.isDebugEnabled()) {
                String message = null;
                try {
                    message = bundle.getString("tiles.dispatchingToTile");
                } catch (MissingResourceException e) {
                    message = "Dispatching to tile {0}";
                synchronized(format) {
                   format.applyPattern(message);
                   message = format.format(new Object[] { tileName });
                log.debug(message);
             dispatchToTile(facesContext, viewToRender, tile);
          else {
             if (log.isDebugEnabled()) {
                String message = null;
                try {
                    message = bundle.getString("tiles.dispatchingToViewHandler");
                } catch (MissingResourceException e) {
                    message = "Dispatching {0} to the default view handler";
                synchronized(format) {
                   format.applyPattern(message);
                   message = format.format(new Object[] { viewId });
                log.debug(message);
             defaultViewHandler.renderView(facesContext, viewToRender);
       private void dispatchToTile(FacesContext facesContext, UIViewRoot viewToRender, ComponentDefinition tile) throws java.io.IOException
           ExternalContext externalContext = facesContext.getExternalContext();
           Object request = externalContext.getRequest();
          Object context = externalContext.getContext();
          TilesContext tilesContext = TilesContextFactory.getInstance(context, request);
          ComponentContext tileContext = ComponentContext.getContext(tilesContext);
          if (tileContext == null) {
             tileContext = new ComponentContext(tile.getAttributes());
             ComponentContext.setContext(tileContext, tilesContext);
          else
             tileContext.addMissing(tile.getAttributes());
          renderTile(facesContext, viewToRender, tile);
          // dispatch to the tile's layout
          //externalContext.dispatch(tile.getPath());
       private void renderTile(FacesContext context, UIViewRoot viewToRender, ComponentDefinition tile) throws IOException, FacesException
           // suppress rendering if "rendered" property on the component is
           // false
           if (!viewToRender.isRendered()) {
               return;
           ExternalContext extContext = context.getExternalContext();
           ServletRequest request = (ServletRequest) extContext.getRequest();
           ServletResponse response = (ServletResponse) extContext.getResponse();
           try {
               if (executePageToBuildView(context, viewToRender, tile)) {
                   response.flushBuffer();
                   //ApplicationAssociate.getInstance(extContext).responseRendered();
                   return;
           } catch (IOException e) {
               throw new FacesException(e);
           // set up the ResponseWriter
           RenderKitFactory renderFactory = (RenderKitFactory)
           FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
           RenderKit renderKit =
                   renderFactory.getRenderKit(context, viewToRender.getRenderKitId());       
           ResponseWriter oldWriter = context.getResponseWriter();
           initBuffSize(context);
           WriteBehindStringWriter strWriter =
                 new WriteBehindStringWriter(context, bufSize);
           ResponseWriter newWriter;
           if (null != oldWriter) {
               newWriter = oldWriter.cloneWithWriter(strWriter);
           } else {
               newWriter = renderKit.createResponseWriter(strWriter, null,
                       request.getCharacterEncoding());           
           context.setResponseWriter(newWriter);
           newWriter.startDocument();
           doRenderView(context, viewToRender);
           newWriter.endDocument();
           // replace markers in the body content and write it to response.
           ResponseWriter responseWriter;
           if (null != oldWriter) {
               responseWriter = oldWriter.cloneWithWriter(response.getWriter());
           } else {
               responseWriter = newWriter.cloneWithWriter(response.getWriter());
           context.setResponseWriter(responseWriter);
           strWriter.flushToWriter(responseWriter);
           if (null != oldWriter) {
               context.setResponseWriter(oldWriter);
           // write any AFTER_VIEW_CONTENT to the response
           writeAfterViewContent(extContext, response);
       private boolean executePageToBuildView(FacesContext context, UIViewRoot viewToExecute, ComponentDefinition tile)
       throws IOException {
           if (null == context) {
               String message = MessageUtils.getExceptionMessageString
                       (MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "context");
               throw new NullPointerException(message);
           if (null == viewToExecute) {
               String message = MessageUtils.getExceptionMessageString
                       (MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "viewToExecute");
               throw new NullPointerException(message);
           String mapping = Util.getFacesMapping(context);
           String requestURI =
                 updateRequestURI(viewToExecute.getViewId(), mapping);
           String requestURI =
               updateRequestURI(tile.getPath(), mapping);
           if (mapping.equals(requestURI)) {
               // The request was to the FacesServlet only - no path info
               // on some containers this causes a recursion in the
               // RequestDispatcher and the request appears to hang.
               // If this is detected, return status 404
               HttpServletResponse response = (HttpServletResponse)
                     context.getExternalContext().getResponse();
               response.sendError(HttpServletResponse.SC_NOT_FOUND);
               return true;
           ExternalContext extContext = context.getExternalContext();
           // update the JSTL locale attribute in request scope so that JSTL
           // picks up the locale from viewRoot. This attribute must be updated
           // before the JSTL setBundle tag is called because that is when the
           // new LocalizationContext object is created based on the locale.
           // PENDING: this only works for servlet based requests
           if (extContext.getRequest()
           instanceof ServletRequest) {
               Config.set((ServletRequest)
               extContext.getRequest(),
                          Config.FMT_LOCALE, context.getViewRoot().getLocale());
           // save the original response
           Object originalResponse = extContext.getResponse();
           // replace the response with our wrapper
           ViewHandlerResponseWrapper wrapped =
                 new ViewHandlerResponseWrapper(
                       (HttpServletResponse)extContext.getResponse());
           extContext.setResponse(wrapped);
           // build the view by executing the page
           extContext.dispatch(requestURI);       
           // replace the original response
           extContext.setResponse(originalResponse);
           // Follow the JSTL 1.2 spec, section 7.4, 
           // on handling status codes on a forward
           if (wrapped.getStatus() < 200 || wrapped.getStatus() > 299) { 
               // flush the contents of the wrapper to the response
               // this is necessary as the user may be using a custom
               // error page - this content should be propagated
               wrapped.flushContentToWrappedResponse();
               return true;           
           // Put the AFTER_VIEW_CONTENT into request scope
           // temporarily
           if (wrapped.isBytes()) {
               extContext.getRequestMap().put(AFTER_VIEW_CONTENT,
                                              wrapped.getBytes());
           } else if (wrapped.isChars()) {
               extContext.getRequestMap().put(AFTER_VIEW_CONTENT,
                                              wrapped.getChars());
           return false;
       }You will also find you need to copy a few other methods from the Sun RI.
    There were a couple of calls to ApplicationAssociate.responseRendered() which I just commented out as well (because they are not visible). They stop people changing the StateManager or ViewHandler after responses have been rendered. Probably not a problem since I will have replaced the ViewHandler anyway.
    Steven

  • Possible to create a custom renderer for rendering standard component ?

    This is in context for creating dynamic Data tables. Is it possible to create a custom Renderer for rendering component (standard) without creating a custom component?
    namanc

    Let's assume you want to create a custom renderer which will be used to render the error-messages (the h:messages tag). The component-family in this case is: javax.faces.Messages, the renderer-type javax.faces.Messages.
    Therefor in your application's faces-config.xml add this renderer-statement (inside a render-kit, obviuosly):
    <faces-config>
      <!-- other stuff like components, managed beans, navigation-rules,... -->
      <render-kit>
        <renderer>
          <component-family>javax.faces.Messages</component-family>
          <renderer-type>javax.faces.Messages</renderer-type>
          <renderer-class>my.very.special.MessagesRenderer</renderer-class>
        </renderer>
      </render-kit>
      <!-- other renderers... -->
    </faces-config>The code for MessagesRenderer is very dependent on your needs, therefor I will not post something here. Basically you need to extend javax.faces.render.Renderer. For help in that camp, surf to the online tutorials or get yourself a book (I learned a lot from Kito Mann's "JSF in Action"). Additionally grab the source for Sun's RI AND Myfaces and dig into that java-code. There is a huge learning potential looking at that source-material.
    hth
    Alexander

  • Custom renderer for radio buttons?

    I want to change how radio buttons are rendered (so they aren't all rendered alone in their own table). What would be the best way to do this?
    One way would be to create a custom component, tag handler, and renderer (and register them all in faces-config.xml).
    But what about using the existing JSF components and just writing my own renderer. Could that work? Would just need to write a renderer and configure faces-config.xml to use the appropriate component-family (for the existing JSF radio button component) and renderer-type (for the existing component tag class for the radio button)�.like this:
    <render-kit>
    <renderer>
    <component-family>javax.faces.SelectOne</component-family>
    <renderer-type>javax.faces.Radio</renderer-type>
    <renderer-class>my.custom.renderer</renderer-class>
    </renderer>
    </render-kit>
    Could this work?
    Thanks.

    Could this work?Yes. Why do you doubt it?

  • Problem with JTree custom renderer when editing

    I have a JTree which uses a custom renderer to display my own icons for different types of nodes. The problem I am having is when I setEditable to true and then attept to edit a node the icon switches back to the default icon, as soon as I am done editing it goes back.
    What I am doing wrong?

    Here is my rendererer
    public class DeviceTreeRenderer extends DefaultTreeCellRenderer implements GuiConstants {
       public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
          JLabel returnValue = (JLabel)super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
          if (value != null) {
             returnValue.setToolTipText(value.toString());
          if (value instanceof Device) {
             returnValue.setIcon(TREE_DEVICE);
             if (!((Device)value).isAlive()) {
                returnValue.setEnabled(false);
          else if (value instanceof GuiPanelGroup) {
             if (expanded) {
                returnValue.setIcon(TREE_PANEL_GROUP_OPEN);
             else {
                returnValue.setIcon(TREE_PANEL_GROUP_CLOSED);
          else if (value instanceof GuiPanel && ((GuiPanel)value).isDirty()) {
             returnValue.setIcon(TREE_PANEL_DIRTY);
          return returnValue;
    }Here is my editor:
    public class WwpJTreeCellEditor extends DefaultTreeCellEditor implements GuiConstants {
          private WwpJTree tree;
           * Creates a new WwpJTreeCellEditor.
           * @param tree The WwpJTree to associate with this editor.
          public WwpJTreeCellEditor(WwpJTree tree) {
             super(tree, (DefaultTreeCellRenderer)tree.getCellRenderer());
             this.tree = tree;
           * Overrides the default isCellEditable so that we check the isEditable() method
           * of the WwpJTreeNodes.
           * @param e An EventObject.
          public boolean isCellEditable(EventObject e) {
             boolean returnValue = super.isCellEditable(e);
             if (returnValue) {
                WwpJTreeNode node = this.tree.getSelectedNode();
                if (node == null || !node.isEditable() || node.isDragging()) {
                   returnValue = false;
             return returnValue;
       }In my JTree I make these calls:
    super.setCellRenderer(new DeviceTreeRenderer());
    super.setCellEditor(new WwpJTreeCellEditor(this));
    super.setEditable(true);

  • Spry Menu Bar 2.0 (1.0) - Handling of widget generated CSS, placement and rendering problems in CSS

    Hello:
    I wanted to repost my question to re-frame the issue based on what I have learned thus far.
    I am working on a website that has been developed using the Spry Menu Bar Framework UI (2.0) I.0, that has some peculiar rendering problems that affect IE 6 in particular.  The CSS is reprinted below.
    In particular, when I post the widget generated CSS in the head as it is orginally situated by the framework, the menu bar works fine.  However, it seemed to me that I should be able to reduce page weight (an important consideration considering my target population) by placing it in the general style sheet governing the entire site.
    When I place the styles at the beginning of the style sheet the menu doesn't render at all in any of the browsers (IE 6+, Firefox, Opera, Safari, Netscape, etc.) as it conflicts with the general rules governing links that appear later in the style sheet.  When I place the styles specific to the Menu bar at the end of the style sheet, then the menu bar renders properly in all browsers except IE 6.
    The odd thing is that the only way to ensure that the menu bar works in IE 6 is to keep the menu related styles in the head of each page.  This raises problems related to page weight (not an insurmountable consideration if no other solution can be found) but still an issue.  Likewise I need to support IE 6, again given the target audience/population.  The issue obviously has something to do with specificity, but I am not certain that is the only consideration at work here.  I have not tried the !important selector in regard to the menu, as IE 6 seems to only partially support this.
    Thanks in advance for any advice or insight that can be provided.  Thanks in particular to Martin for his contributions to my earlier question related to this issue.
    Steve Webster.
    The CSS governing the horizontal menu bar is as follows:  (currently the following CSS is embedded in the head of the web page)
    <style type="text/css">
    /*  -- Begins Spry Menu Widget 2.0 (1.0) Horizontal menu bar Custom styles --  */
    /* BeginOAWidget_Instance_2141544: #MenuBar */
    /* Settable values for skinning a Basic menu via presets. If presets are not sufficient, most skinning should be done in
       these rules, with the exception of the images used for down or rightpointing arrows, which are in the file SpryMenuBasic.css
         These assume the following widget classes for menu layout (set in a preset)
       .MenuBar - Applies to all menubars - default is horizontal bar, allsubmenus are vertical - 2nd level subs and beyond are pull-right.
        .MenuBarVertical - vertical main bar; all submenus are pull-right.
       You can also pass in extra classnames to set your desired top levelmenu bar layout. Normally, these are set by using a preset.
        They only apply to horizontal menu bars:
            MenuBarLeftShrink - The menu bar will be horizontally 'shrinkwrapped' to be just large enough to hold its items, and left aligned
            MenuBarRightShrink - Just like MenuBarLeftShrink, but right aligned
            MenuBarFixedLeft - Fixed at a specified width set in the rule '.MenuBarFixedLeft', and left aligned. 
            MenuBarFixedCentered -  - Fixed at a specified width set in the rule '.MenuBarFixedCentered',
                            and centered in its parent container.
            MenuBarFullwidth - Grows to fill its parent container width.
        In general, all rules specified in this file are prefixed by #MenuBar so they only apply to instances of the widget inserted along
       with the rules. This permits use of multiple MenuBarBasic widgets onthe same page with different layouts. Because of IE6 limitations,
        there are a few rules where this was not possible. Those rules are so noted in comments.
    #MenuBar  {
        background-color:transparent;
       font-family: Arial, Helvetica, sans-serif; /* Specify fonts on onMenuBar and subMenu MenuItemContainer, so MenuItemContainer,
                                                    MenuItem, and MenuItemLabel
                                                    at a given level all use same definition for ems.
                                                    Note that this means the size is also inherited to child submenus,
                                                    so use caution in using relative sizes other than
                                                    100% on submenu fonts. */
        font-weight: normal;
        font-size: 17px;
        font-style: normal;
        padding:0;
    /* Caution: because ID+class selectors do not work properly in IE6, but we want to restrict these rules to just this
    widget instance, we have used string-concatenated classnames for our selectors for the layout type of the menubar
    in this section. These have very low specificity, so be careful not to accidentally override them. */
    .MenuBar br { /* using just a class so it has same specificity as the ".MenuBarFixedCentered br" rule bleow */
        display:none;
    .MenuBarLeftShrink {
        float: left; /* shrink to content, as well as float the MenuBar */
        width: auto;
    .MenuBarRightShrink {
        float: right; /* shrink to content, as well as float the MenuBar */
        width: auto;
    .MenuBarFixedLeft {
        float: left;
        width: 80em;
    .MenuBarFixedCentered {
        float: none;
        width: 80em;
        margin-left:auto;
        margin-right:auto;
    .MenuBarFixedCentered br {
        clear:both;
        display:block;
    .MenuBarFixedCentered .SubMenu br {
        display:none;
    .MenuBarFullwidth {
        float: left;
        width: 100%;
    /* Top level menubar items - these actually apply to all items, and get overridden for 1st or successive level submenus */
    #MenuBar  .MenuItemContainer {
        padding: 0px 0px 0px 0px;
        margin: 0;     /* Zero out margin  on the item containers. The MenuItem is the active hover area.
                    For most items, we have to do top or bottom padding or borders only on the MenuItem
                    or a child so we keep the entire submenu tiled with items.
                    Setting this to 0 avoids "dead spots" for hovering. */
    #MenuBar  .MenuItem {
        padding: 10px 10px 10px 4px;
        background-color:#000088;
        background-image:url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/Nav igation%20Bar%20Segment-Dark.png);
        background-repeat:repeat-x;       
    #MenuBar  .MenuItemFirst {
        border-style: none none none none;
    #MenuBar .MenuItemLast {
        border-style: none none none none;
    #MenuBar  .MenuItem  .MenuItemLabel{
        text-align:center;
        line-height:1.4em;
        color:#ffffff;
        background-color:transparent;
        padding: 0px 18px 0px 5px;
        width: 10em;
        width:auto;
    .SpryIsIE6 #MenuBar  .MenuItem  .MenuItemLabel{
        width:1em; /* Equivalent to min-width in modern browsers */
    /* First level submenu items */
    #MenuBar .SubMenu  .MenuItem {
        font-family: Arial, Helvetica, sans-serif;
        font-weight: bold;
        font-size: 15px;
        font-style: normal;
        background-color:#000088;
        padding:0px 2px 0px 0px;
        border-width:0px;
        border-color: #cccccc #cccccc #cccccc #cccccc;
        /* Border styles are overriden by first and last items */
        border-style: solid solid none solid;
    #MenuBar  .SubMenu .MenuItemFirst {
        border-style: none;
        padding: 0px;
    #MenuBar  .SubMenu .MenuItemFirst .MenuItemLabel{
        padding-top: 0px;
    #MenuBar .SubMenu .MenuItemLast {
        border-style: none none none none;
    #MenuBar .SubMenu .MenuItemLast .MenuItemLabel{
        padding-bottom: 10px;
    #MenuBar .SubMenu .MenuItem .MenuItemLabel{
        text-align:left;
        line-height:1em;   
        background-color:transparent;
        color:#ffffff;
        padding: 10px 10px 10px 10px;
        width: 240px;
    /* Hover states for containers, items and labels */
    #MenuBar .MenuItemHover {
        background-color: #2E35A3;
        background-image:url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/Nav igation%20Bar%20Segment%20Light2.png);
        background-repeat:repeat-x;
    #MenuBar .MenuItemWithSubMenu.MenuItemHover .MenuItemLabel{
        background-color: transparent; /* consider exposing this prop separately*/
        color: #ffffff;
    #MenuBar .MenuItemHover .MenuItemLabel{
        background-color: transparent;
        color: #ffffff;
    #MenuBar .SubMenu .MenuItemHover {
        background-color:#2E35A3;
    #MenuBar .SubMenu .MenuItemHover .MenuItemLabel{
        background-color: transparent;
        color: #ffffff;
    /* Submenu properties -- First level of submenus */
    #MenuBar .SubMenuVisible {
        background-color: transparent;
       min-width:0%;  /* This keeps the menu from being skinnier than theparent MenuItemContainer - nice to have but not available on ie6 */
        border-style: none none none none;
    #MenuBar.MenuBar .SubMenuVisible {/* For Horizontal menubar only */
        top: 100%;    /* 100% is at the bottom of parent menuItemContainer */
        left:0px; /* 'left' may need tuning depending upon borders or padding applied to menubar MenuItemContainer or MenuItem,
                        and your personal taste.
                       0px will left align the dropdown with the content area of theMenuItemContainer. Assuming you keep the margins 0
                        on MenuItemContainer and MenuItem on the parent
                        menubar, making this equal the sum of the MenuItemContainer & MenuItem padding-left will align
                        the dropdown with the left of the menu item label.*/
        z-index:10;
    #MenuBar.MenuBarVertical .SubMenuVisible {
        top: 0px;   
        left:100%;
        min-width:0px; /* Do not neeed to match width to parent MenuItemContainer - items will prevent total collapse */
    /* Submenu properties -- Second level submenu and beyond - these are visible descendents of .MenuLevel1 */
    #MenuBar .MenuLevel1 .SubMenuVisible {
        background-color: transparent;
        min-width:0px; /* Do not neeed to match width to parent MenuItemContainer - items will prevent total collapse*/
        top: 0px;    /* If desired, you can move this down a smidge to separate top item''s submenu from menubar -
                    that is really only needed for submenu on first item of MenuLevel1, or you can make it negative to make submenu more
                    vertically 'centered' on its invoking item */
        left:100%; /* If you want to shift the submenu left to partially cover its invoking item, you can add a margin-left with a
                    negative value to this rule. Alternatively, if you use fixed-width items, you can change this left value
                    to use px or ems to get the offset you want. */
    /* IE6 rules - you can delete these if you do not want to support IE6 */
    /* A note about multiple classes in IE6.
    * Some of the rules above use multiple class names on an element forselection, such as "hover" (MenuItemHover) and "has a subMenu"(MenuItemWithSubMenu),
    * giving the selector '.MenuItemWithSubMenu.MenuItemHover'.
    * Unfortunately IE6 does not support using mutiple classnames in aselector for an element. For a selector such as '.foo.bar.baz', IE6ignores
    * all but the final classname (here, '.baz'), and sets thespecificity accordingly, counting just one of those classs assignificant. To get around this
    * problem, we use the plugin in SpryMenuBarIEWorkaroundsPlugin.js to generate compound classnames for IE6, such as 'MenuItemWithSubMenuHover'.
    * Since there are a lotof these needed, the plugin does not generate the extra classes formodern browsers, and we use the CSS2 style mutltiple class
    * syntax for that. Since IE6 both applies rules where
    * it should not, and gets the specificity wrong too, we have to order rules carefully, so the rule misapplied in IE6 can be overridden.
    * So, we put the multiple class rule first. IE6 will mistakenly apply this rule.  We follow this with the single-class rule that it would
    * mistakenly override, making sure the  misinterpreted IE6 specificity is the same as the single-class selector, so the latter wins.
    * We then create a copy of the multiple class rule, adding a '.SpryIsIE6' class as context, and making sure the specificity for
    * the selector is high enough to beat the single-class rule in the "both classes match" case. We place the IE6 rule at the end of the
    * css style block to make it easy to delete if you want to drop IE6 support.
    * If you decide you do not need IE6 support, you can get rid of these,as well as the inclusion of the SpryMenuBarIEWorkaroundsPlugin.jsscript.
    * The 'SpryIsIE6' class is placed on the HTML element by the script in SpryMenuBarIEWorkaroundsPlugin.js if the browser isInternet Explorer 6. This avoids the necessity of IE conditionalcomments for these rules.
    .SpryIsIE6 #MenuBar .MenuBarView .MenuItemWithSubMenuHover .MenuItemLabel /* IE6 selector  */{
        background-color: transparent; /* consider exposing this prop separately*/
        color: #ffffff;
    .SpryIsIE6 #MenuBar .MenuBarView .SubMenu .MenuItemWithSubMenuHover .MenuItemLabel/* IE6 selector  */{
        background-color: transparent; /* consider exposing this prop separately*/
        color: #ffffff;
    .SpryIsIE6 #MenuBar .SubMenu .SubMenu  /* IE6 selector  */{
        margin-left: -0px; /* Compensates for at least part of an IE6 "double padding" version of the "double margin" bug */
    /* EndOAWidget_Instance_2141544 */
    /* Ends Spry Menu Bar Widget 2.0 (1.0) Horizontal Menu Custom styles */
    </style>
    The CSS governing the site generally is reproduced below:  (my belief is that it is the a:link, a:visited,  a:hover, a:active styles that may be in conflict).
    @charset "utf-8";
    body  {
        font: 100% Verdana, Arial, Helvetica, sans-serif;
       min-height: 0; /* This is necessary to overcome the "haslayout" bugthat is found in Windows 7 in conjuction with IE8.  For Moreinformation see: URL -- http://reference.sitepoint.com/css/haslayout.html */
        margin: 0; /* it's good practice to zero the margin and padding of the body element to account for differing browser defaults */
        padding: 0;
        text-align:center; /* This allows for the centering of the container and overcomes a bug inherent in IE 5 */
        color: #000000;
        list-style-image: none;
        background-color: #FCFCFC;
    h1,h2,h3,h4,h5,h6 {
    color:#000066;
    a:link {
        color: #151A96;
        text-decoration: underline;
    a:visited {
        text-decoration: underline;
        color: #1B8DCD;
    a:hover {
        text-decoration: none;
        color: #F30A0A;
    a:active {
        text-decoration: underline;
        color: #151A96;
    #container {
        width: 960px;   
        margin: 0 auto; /* the auto margins (in conjunction with a width) center the page */
        text-align: left; /* this overrides the text-align: center on the body element. */
        background-image:
        url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/Website%20Midsection %20_960.png);
        background-repeat: repeat-y;
    #header {
           padding: 0;  /* this padding matches the left alignment of the elementsin the divs that appear beneath it. If an image is used in the #headerinstead of text, you may want to remove the padding. */
            width:960px;
            height:332px;
            background-image:
            url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/Website%20Header_960 .png);
            background-repeat:no-repeat;
    #header h1 {
        margin-right: 0px; /* zeroing the margin of the last element in the #header div will avoid margin collapse - an unexplainable space between divs. If the div has a border around it, this is not necessary as that also avoids the margin collapse */
        padding: 0; /* using padding instead of margin will allow you to keep the element away from the edges of the div */
        display:none;
    #header img {
        display: none;
    #Main_nav_contents {
        padding: 0;
        margin-top: 0px;
        height: 39px;
        width: 950px;       
        padding-top: 275px; 
        padding-left: 39px;
        z-index: 3; 
    #MenuBarVertical {
        margin-bottom: 50px;
        padding-top: 50px;
        padding-bottom:200px;
        padding-left: 15px;
        padding-right: 15px;
    .mainContent_left {
       margin: 0;/* the right margin on this div element creates the columndown the right side of the page - no matter how much content thesidebar1 div contains, the column space will remain. You can removethis margin if you want the #mainContent div's text to fill the#sidebar1 space when the content in #sidebar1 ends. */
        padding-left:30px;
        padding-right:20px; /* remember that padding is the space inside the div box and margin is the space outside the div box */
        width: 600px;
        float: left;
    .sidebar_right {
        float: right; /* since this element is floated, a width must be given */
        width: 270px; /* the actual width of this div, in standards-compliant browsers, or standards mode in Internet Explorer will include the padding and border in addition to the width */
        margin-top: 30px;
        margin-left:0;
        margin-right:10px;
        font-size:90%;
    .mainContent_right {
        margin-left: 10px;
        padding-left:30px;
        padding-right:20px;
        width: 600px;
        float: right;
    .sidebar_left {
        float: left; /* since this element is floated, a width must be given */
        width: 270px; /* the actual width of this div, in standards-compliant browsers, or standards mode in Internet Explorer will include the padding and border in addition to the width */
        margin-top: 30px;
        margin-left:30px;
        margin-right:0;
        overflow: hidden;
        font-size:90%;
    .main_content_centered {
        width: 650px;
        margin-left: 155px;
    .main_content_centered_header {
        margin-left: 75px;
    .sidebar_textbox {
        margin: 0px;   
        width: 260px;
        padding: 2px;
    .sidebar_textbox_header {
        width:255px;
        height:58px;
        background-image:url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/Por trait%20Textbox%20Header.png);
    .sidebar_textbox_background_middle {
         width: 255px;   
        padding-top: 12px;   
        padding-bottom: 10px;
        background-image:url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/Por trait%20Textbox%20Middle.png);
        background-repeat: repeat-y;
    .sidebar_textbox_content {
       /* The width and padding are set as follows to accomodate quirks inbrowser rendering and to ensure that text is contained within thebackground of the text box */
        width: 230px;
        padding-left: 20px;
        padding-right: 40px;
    .sidebar_textbox_footer {
        width:255px;
        height:64px;
    background-image:url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/Port rait%20Textbox%20Footer.png);
    #issues_menu a:link {
        color: #151A96;
        text-decoration: none;
        font-weight:bold;
    #issues_menu a:visited {
        color: #151A96;
        font-weight:bold;
        text-decoration: none;
    #issues_menu a:hover {   
        color: #F30A0A;
        font-weight:bold;
        font-style: oblique;
        text-decoration: none;
    #issues_menu a:active {
        color: #151A96;
        font-weight:bold;
        text-decoration: none;
    #archives {
        padding-top: 15px;
        padding-right: 15px;
        padding-bottom: 20px;
        padding-left: 0px;
    .landscape_textbox {
        width: 500px;
        margin-right: 0px;
        margin-left: 30px;
        padding-top:35px;
        padding-bottom: 25px;
        font-style: normal;
        font-weight: normal;
    .landscape_textbox_hdr {
        width:500px;
        height:38px;
        margin:auto;
        padding:0;
        background-image:
    url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/Landscape%20Textbox%2 0Header.png);
    .landscape_textbox_middle {
        width:auto;
        margin:auto;
        padding-top: 12px;
        padding-bottom: 12px;
        background-image:url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/lan dscapte%20Textbox%20Middle.png);
        background-repeat:repeat-y;
    .landscape_textbox_content {
        width:450px;
        padding:25px;
    .landscape_textbox_ftr {
        width:500px;
        height:44px;
        margin:auto;
        padding:0;
        background-image:url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/Lan dscape%20Textbox%20Footer.png);
    #footer {
        padding: 0; /* this padding matches the left alignment of the elements in the divs that appear above it. */
        width: 960px;
        height: 222px;
        background-image:
        url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/Website%20Footer%20_ 960.png);
        background-repeat:no-repeat;
    #footer p {
       margin: 0px; /* zeroing the margins of the first element in the footerwill avoid the possibility of margin collapse - a space between divs */
        padding:0px; /* padding on this element will create space, just as the the margin would have, without the margin collapse issue */
        text-align:center;
        margin-left: 50px;
        margin-right: 50px;
        padding: 10px;
        font-size: small;
    #footer h5 {
    text-align:center;
    .fltrt { /* this class can be used to float an element right in your page. The floated element must precede the element it should be next to on the page. */
        float: right;
        margin-left: 8px;
    .fltlft { /* this class can be used to float an element left in your page */
        float: left;
        margin-right: 8px;
    .clearfloat { /* this class should be placed on a div or break element and should be the final element before the close of a container that should fully contain a float */
        clear:both;
        height:0;
        font-size: 1px;
        line-height: 0px;
    .dropcap {
        display: block;
        float: left;
        line-height: 80%;
        font-size: 250%;
        font-weight: bolder;
        color: #000066;   
        padding: .03em .1em 0 0;
    .red_arrows {
        list-style-position: outside;
        list-style-image: url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/Arrow%20Large.png);    
    .blue_bullets {
        list-style-position: outside;
        list-style-image: url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/Bullet%20Medium%20Fu ll.png);   
    .attention {
        color: #F30A0A;
        font-size:x-large;
        font-family: Georgia, "Times New Roman", Times, serif;
        font-style: italic;
        font-weight:900;
    .attention_small {
        color: #F30A0A;
        font-size:large;
        font-family: Georgia, "Times New Roman", Times, serif;
        font-style: italic;
        font-weight:900;
    .table {
        table-layout:fixed;
    .blue {
        color: #00F;
    #container .mainContent_left p .blue {
        color: #0303A0;

    Hi Nancy:
    The specific code that I am referring to is the CSS code governing the styling of the spry menu widget that only works in IE 6 if, and only if, it remains in the head of the web page.  If removed and placed in a stylesheet, the IE plugins fail to compensate for the IE 6 "gap" bug.  As I said, it doesn't make sense to me that, assuming specificity is addressed, that these can not be included in an external style sheet.  I am looking for a) an explanation why they must remain embedded in the web page; and 2) any means by which I might be able to export them.
    I will reproduce the specific css style (code) below:  it should also be visable through reveal source --
    Thanks again, Steve Webster.
    The CSS governing the horizontal menu bar is as follows:  (currently the following CSS is embedded in the head of the web page)
    <style type="text/css">
    /*  -- Begins Spry Menu Widget 2.0 (1.0) Horizontal menu bar Custom styles --  */
    /* BeginOAWidget_Instance_2141544: #MenuBar */
    /* Settable values for skinning a Basic menu via presets. If presets are not sufficient, most skinning should be done in
       these rules, with the exception of the images used for down or rightpointing arrows, which are in the file SpryMenuBasic.css
         These assume the following widget classes for menu layout (set in a preset)
       .MenuBar - Applies to all menubars - default is horizontal bar, allsubmenus are vertical - 2nd level subs and beyond are pull-right.
        .MenuBarVertical - vertical main bar; all submenus are pull-right.
       You can also pass in extra classnames to set your desired top levelmenu bar layout. Normally, these are set by using a preset.
        They only apply to horizontal menu bars:
            MenuBarLeftShrink - The menu bar will be horizontally 'shrinkwrapped' to be just large enough to hold its items, and left aligned
            MenuBarRightShrink - Just like MenuBarLeftShrink, but right aligned
            MenuBarFixedLeft - Fixed at a specified width set in the rule '.MenuBarFixedLeft', and left aligned. 
            MenuBarFixedCentered -  - Fixed at a specified width set in the rule '.MenuBarFixedCentered',
                            and centered in its parent container.
            MenuBarFullwidth - Grows to fill its parent container width.
        In general, all rules specified in this file are prefixed by #MenuBar so they only apply to instances of the widget inserted along
       with the rules. This permits use of multiple MenuBarBasic widgets onthe same page with different layouts. Because of IE6 limitations,
        there are a few rules where this was not possible. Those rules are so noted in comments.
    #MenuBar  {
        background-color:transparent;
       font-family: Arial, Helvetica, sans-serif; /* Specify fonts on onMenuBar and subMenu MenuItemContainer, so MenuItemContainer,
                                                    MenuItem, and MenuItemLabel
                                                    at a given level all use same definition for ems.
                                                    Note that this means the size is also inherited to child submenus,
                                                    so use caution in using relative sizes other than
                                                    100% on submenu fonts. */
        font-weight: normal;
        font-size: 17px;
        font-style: normal;
        padding:0;
    /* Caution: because ID+class selectors do not work properly in IE6, but we want to restrict these rules to just this
    widget instance, we have used string-concatenated classnames for our selectors for the layout type of the menubar
    in this section. These have very low specificity, so be careful not to accidentally override them. */
    .MenuBar br { /* using just a class so it has same specificity as the ".MenuBarFixedCentered br" rule bleow */
        display:none;
    .MenuBarLeftShrink {
        float: left; /* shrink to content, as well as float the MenuBar */
        width: auto;
    .MenuBarRightShrink {
        float: right; /* shrink to content, as well as float the MenuBar */
        width: auto;
    .MenuBarFixedLeft {
        float: left;
        width: 80em;
    .MenuBarFixedCentered {
        float: none;
        width: 80em;
        margin-left:auto;
        margin-right:auto;
    .MenuBarFixedCentered br {
        clear:both;
        display:block;
    .MenuBarFixedCentered .SubMenu br {
        display:none;
    .MenuBarFullwidth {
        float: left;
        width: 100%;
    /* Top level menubar items - these actually apply to all items, and get overridden for 1st or successive level submenus */
    #MenuBar  .MenuItemContainer {
        padding: 0px 0px 0px 0px;
        margin: 0;     /* Zero out margin  on the item containers. The MenuItem is the active hover area.
                    For most items, we have to do top or bottom padding or borders only on the MenuItem
                    or a child so we keep the entire submenu tiled with items.
                    Setting this to 0 avoids "dead spots" for hovering. */
    #MenuBar  .MenuItem {
        padding: 10px 10px 10px 4px;
        background-color:#000088;
        background-image:url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/Nav igation%20Bar%20Segment-Dark.png);
        background-repeat:repeat-x;       
    #MenuBar  .MenuItemFirst {
        border-style: none none none none;
    #MenuBar .MenuItemLast {
        border-style: none none none none;
    #MenuBar  .MenuItem  .MenuItemLabel{
        text-align:center;
        line-height:1.4em;
        color:#ffffff;
        background-color:transparent;
        padding: 0px 18px 0px 5px;
        width: 10em;
        width:auto;
    .SpryIsIE6 #MenuBar  .MenuItem  .MenuItemLabel{
        width:1em; /* Equivalent to min-width in modern browsers */
    /* First level submenu items */
    #MenuBar .SubMenu  .MenuItem {
        font-family: Arial, Helvetica, sans-serif;
        font-weight: bold;
        font-size: 15px;
        font-style: normal;
        background-color:#000088;
        padding:0px 2px 0px 0px;
        border-width:0px;
        border-color: #cccccc #cccccc #cccccc #cccccc;
        /* Border styles are overriden by first and last items */
        border-style: solid solid none solid;
    #MenuBar  .SubMenu .MenuItemFirst {
        border-style: none;
        padding: 0px;
    #MenuBar  .SubMenu .MenuItemFirst .MenuItemLabel{
        padding-top: 0px;
    #MenuBar .SubMenu .MenuItemLast {
        border-style: none none none none;
    #MenuBar .SubMenu .MenuItemLast .MenuItemLabel{
        padding-bottom: 10px;
    #MenuBar .SubMenu .MenuItem .MenuItemLabel{
        text-align:left;
        line-height:1em;   
        background-color:transparent;
        color:#ffffff;
        padding: 10px 10px 10px 10px;
        width: 240px;
    /* Hover states for containers, items and labels */
    #MenuBar .MenuItemHover {
        background-color: #2E35A3;
        background-image:url(../ACLCO%20Graphics%20-%20Web%20site%20Parts/Nav igation%20Bar%20Segment%20Light2.png);
        background-repeat:repeat-x;
    #MenuBar .MenuItemWithSubMenu.MenuItemHover .MenuItemLabel{
        background-color: transparent; /* consider exposing this prop separately*/
        color: #ffffff;
    #MenuBar .MenuItemHover .MenuItemLabel{
        background-color: transparent;
        color: #ffffff;
    #MenuBar .SubMenu .MenuItemHover {
        background-color:#2E35A3;
    #MenuBar .SubMenu .MenuItemHover .MenuItemLabel{
        background-color: transparent;
        color: #ffffff;
    /* Submenu properties -- First level of submenus */
    #MenuBar .SubMenuVisible {
        background-color: transparent;
       min-width:0%;  /* This keeps the menu from being skinnier than theparent MenuItemContainer - nice to have but not available on ie6 */
        border-style: none none none none;
    #MenuBar.MenuBar .SubMenuVisible {/* For Horizontal menubar only */
        top: 100%;    /* 100% is at the bottom of parent menuItemContainer */
        left:0px; /* 'left' may need tuning depending upon borders or padding applied to menubar MenuItemContainer or MenuItem,
                        and your personal taste.
                       0px will left align the dropdown with the content area of theMenuItemContainer. Assuming you keep the margins 0
                        on MenuItemContainer and MenuItem on the parent
                        menubar, making this equal the sum of the MenuItemContainer & MenuItem padding-left will align
                        the dropdown with the left of the menu item label.*/
        z-index:10;
    #MenuBar.MenuBarVertical .SubMenuVisible {
        top: 0px;   
        left:100%;
        min-width:0px; /* Do not neeed to match width to parent MenuItemContainer - items will prevent total collapse */
    /* Submenu properties -- Second level submenu and beyond - these are visible descendents of .MenuLevel1 */
    #MenuBar .MenuLevel1 .SubMenuVisible {
        background-color: transparent;
        min-width:0px; /* Do not neeed to match width to parent MenuItemContainer - items will prevent total collapse*/
        top: 0px;    /* If desired, you can move this down a smidge to separate top item''s submenu from menubar -
                    that is really only needed for submenu on first item of MenuLevel1, or you can make it negative to make submenu more
                    vertically 'centered' on its invoking item */
        left:100%; /* If you want to shift the submenu left to partially cover its invoking item, you can add a margin-left with a
                    negative value to this rule. Alternatively, if you use fixed-width items, you can change this left value
                    to use px or ems to get the offset you want. */
    /* IE6 rules - you can delete these if you do not want to support IE6 */
    /* A note about multiple classes in IE6.
    * Some of the rules above use multiple class names on an element forselection, such as "hover" (MenuItemHover) and "has a subMenu"(MenuItemWithSubMenu),
    * giving the selector '.MenuItemWithSubMenu.MenuItemHover'.
    * Unfortunately IE6 does not support using mutiple classnames in aselector for an element. For a selector such as '.foo.bar.baz', IE6ignores
    * all but the final classname (here, '.baz'), and sets thespecificity accordingly, counting just one of those classs assignificant. To get around this
    * problem, we use the plugin in SpryMenuBarIEWorkaroundsPlugin.js to generate compound classnames for IE6, such as 'MenuItemWithSubMenuHover'.
    * Since there are a lotof these needed, the plugin does not generate the extra classes formodern browsers, and we use the CSS2 style mutltiple class
    * syntax for that. Since IE6 both applies rules where
    * it should not, and gets the specificity wrong too, we have to order rules carefully, so the rule misapplied in IE6 can be overridden.
    * So, we put the multiple class rule first. IE6 will mistakenly apply this rule.  We follow this with the single-class rule that it would
    * mistakenly override, making sure the  misinterpreted IE6 specificity is the same as the single-class selector, so the latter wins.
    * We then create a copy of the multiple class rule, adding a '.SpryIsIE6' class as context, and making sure the specificity for
    * the selector is high enough to beat the single-class rule in the "both classes match" case. We place the IE6 rule at the end of the
    * css style block to make it easy to delete if you want to drop IE6 support.
    * If you decide you do not need IE6 support, you can get rid of these,as well as the inclusion of the SpryMenuBarIEWorkaroundsPlugin.jsscript.
    * The 'SpryIsIE6' class is placed on the HTML element by the script in SpryMenuBarIEWorkaroundsPlugin.js if the browser isInternet Explorer 6. This avoids the necessity of IE conditionalcomments for these rules.
    .SpryIsIE6 #MenuBar .MenuBarView .MenuItemWithSubMenuHover .MenuItemLabel /* IE6 selector  */{
        background-color: transparent; /* consider exposing this prop separately*/
        color: #ffffff;
    .SpryIsIE6 #MenuBar .MenuBarView .SubMenu .MenuItemWithSubMenuHover .MenuItemLabel/* IE6 selector  */{
        background-color: transparent; /* consider exposing this prop separately*/
        color: #ffffff;
    .SpryIsIE6 #MenuBar .SubMenu .SubMenu  /* IE6 selector  */{
        margin-left: -0px; /* Compensates for at least part of an IE6 "double padding" version of the "double margin" bug */
    /* EndOAWidget_Instance_2141544 */
    /* Ends Spry Menu Bar Widget 2.0 (1.0) Horizontal Menu Custom styles */
    </style>

  • Help! Using a custom renderer to display an image

    I have a JTable where I want to set the renderer of one column to a custom renderer. And I want this renderer to show either a play button image, or a stop button image, depending on the status, which is a Boolean value. However, the image won't show up when I run the application. Here's the code from the renderer...
    public class StatusRenderer extends DefaultTableCellRenderer {
    private ImageIcon playIcon = new ImageIcon("C:/play.jpg");
    private ImageIcon stopIcon = new ImageIcon("C:/stop.jpg");
    public StatusRenderer() {
    setHorizontalAlignment(JLabel.CENTER);
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
    Boolean b = (Boolean) value;
    setIcon(b.booleanValue() ? playIcon : stopIcon);
    return this;
    The application runs, but no icon shows up in the table cell. I'd really appreciate any help on this. Thanks.

    look at http://www2.gol.com/users/tame/swing/examples/JTableExamples1.html
    for some great table examples (they may need minor mods to work on 1.3/1.4)
    Basically I think you need something more like:
    public class StatusRenderer extends JLabel
      implements DefaultTableCellRenderer
        public StatusRenderer() {
            super();
            setHorizontalAlignment(JLabel.CENTER);
        public Component getTableCellRendererComponent(JTable table,
                                           Object value, boolean sSelected,
                                           boolean hasFocus, int row,
                                           int col)
            Boolean b = (Boolean) value;
            setIcon(b.booleanValue() ? playIcon : stopIcon);
            return this;
    }Don't forget to add the renderer to the column you want it in !

  • JTree custom renderer setting selection background color problem

    Hi,
    I have a JTree with a custom icon renderer that displays an icon. The JTree is part of a TreeTable component. Iam having a problem setting the selection background uniformly for the entire row. There is no problem when there is no row selected in the JTable.
    My present code looks like this:
    Iam overriding paint in my renderer which extends DefaultCellRenderer.
           super.paint(g);
            Color bColor = null;
            if(!m_selected) {
                 if(currRow % 2 == 0) {
                      bColor = Color.WHITE;
                 } else {
                                                    bColor = backColor;
            } else {
                 bColor = table.getSelectionBackground();                  bColor = getRowSelectionColor();
         if(bColor != null) {
                           g.setColor(bColor);
             if(!m_selected) {
                   g.setXORMode(new Color(0xFF, 0xFF, 0xFF));
             } else {
                 g.setXORMode(new Color(0x00, 0x00, 0x00));
                  I have a color I arrive at using some algorithm that I want using method getRowSelectionColor(). The other cells in the row have this color. But the cell containing the tree node shows different color. Iam not able to arrive at the right combination of the color to set and the xor color so my tree node also looks like the other cells in the row.
    It is not a problem really as the table still looks good. Its just that the tree node looks like it has been highlighted and this might cause a problem when a table cell is highlighed later on in the application ( two cells in the row would be highlighted causing confusion).
    Any help would be appreciated.
    Regards,
    vidyut

    Hi Camickr,
    Thanks for the reply. Iam sorry I didn't include the sources the first time around. There were too many of them. I have created a small, self-contained, compilable program that demonstrates the problem and including it herewith. Still there's quite many files but they are all needed Iam afraid. The only one you will have to concern yourself fior this problem is the file IconRenderer.java. The treenode background and the other cells background are not in sync when table row is not selected in this example though. But they are in my real program. I just need them to be in sync i.e have the same background color when the row is selected.
    Your help would be very much appreciated.
    These are the files that are included below:
    1. AbstractTreeTableModel.java
    2. Bookmarks.java
    3. BookmarksModel.java
    4. DynamicTreeTableModel.java
    5. IconRenderer.java
    6. IndicatorRenderer.java
    7. JTreeTable.java
    8. TreeTableExample3.java (contains main)
    9. TreeTableModel.java
    10. TreeTableModelAdapter.java
    The copyright and javadocs information has been stripped for clarity.
    cheers,
    vidyut
    // AbstractTreeTableModel.java BEGIN
    import javax.swing.tree.*;
    import javax.swing.event.*;
    public abstract class AbstractTreeTableModel implements TreeTableModel {
        protected Object root;    
        protected EventListenerList listenerList = new EventListenerList();
        public AbstractTreeTableModel(Object root) {
            this.root = root;
        // Default implementations for methods in the TreeModel interface.
        public Object getRoot() {
            return root;
        public boolean isLeaf(Object node) {
            return getChildCount(node) == 0;
        public void valueForPathChanged(TreePath path, Object newValue) {}
        // This is not called in the JTree's default mode:
        // use a naive implementation.
        public int getIndexOfChild(Object parent, Object child) {
            for (int i = 0; i < getChildCount(parent); i++) {
             if (getChild(parent, i).equals(child)) {
                 return i;
         return -1;
        public void addTreeModelListener(TreeModelListener l) {
            listenerList.add(TreeModelListener.class, l);
        public void removeTreeModelListener(TreeModelListener l) {
            listenerList.remove(TreeModelListener.class, l);
        protected void fireTreeNodesChanged(Object source, Object[] path,
                                            int[] childIndices,
                                            Object[] children) {
            // Guaranteed to return a non-null array
            Object[] listeners = listenerList.getListenerList();
            TreeModelEvent e = null;
            // Process the listeners last to first, notifying
            // those that are interested in this event
            for (int i = listeners.length-2; i>=0; i-=2) {
                if (listeners==TreeModelListener.class) {
    // Lazily create the event:
    if (e == null)
    e = new TreeModelEvent(source, path,
    childIndices, children);
    ((TreeModelListener)listeners[i+1]).treeNodesChanged(e);
    protected void fireTreeNodesInserted(Object source, Object[] path,
    int[] childIndices,
    Object[] children) {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    TreeModelEvent e = null;
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length-2; i>=0; i-=2) {
    if (listeners[i]==TreeModelListener.class) {
    // Lazily create the event:
    if (e == null)
    e = new TreeModelEvent(source, path,
    childIndices, children);
    ((TreeModelListener)listeners[i+1]).treeNodesInserted(e);
    protected void fireTreeNodesRemoved(Object source, Object[] path,
    int[] childIndices,
    Object[] children) {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    TreeModelEvent e = null;
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length-2; i>=0; i-=2) {
    if (listeners[i]==TreeModelListener.class) {
    // Lazily create the event:
    if (e == null)
    e = new TreeModelEvent(source, path,
    childIndices, children);
    ((TreeModelListener)listeners[i+1]).treeNodesRemoved(e);
    protected void fireTreeStructureChanged(Object source, Object[] path,
    int[] childIndices,
    Object[] children) {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    TreeModelEvent e = null;
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for (int i = listeners.length-2; i>=0; i-=2) {
    if (listeners[i]==TreeModelListener.class) {
    // Lazily create the event:
    if (e == null)
    e = new TreeModelEvent(source, path,
    childIndices, children);
    ((TreeModelListener)listeners[i+1]).treeStructureChanged(e);
    // Default impelmentations for methods in the TreeTableModel interface.
    public Class getColumnClass(int column) { return Object.class; }
    public boolean isCellEditable(Object node, int column) {
    return getColumnClass(column) == TreeTableModel.class;
    public void setValueAt(Object aValue, Object node, int column) {}
    // Left to be implemented in the subclass:
    * public Object getChild(Object parent, int index)
    * public int getChildCount(Object parent)
    * public int getColumnCount()
    * public String getColumnName(Object node, int column)
    * public Object getValueAt(Object node, int column)
    // AbstractTreeTableModel.java END
    // Bookmarks.java BEGIN
    import java.io.*;
    import java.net.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.tree.*;
    import javax.swing.text.*;
    import javax.swing.text.html.*;
    import javax.swing.text.html.parser.*;
    public class Bookmarks {
    /** The root node the bookmarks are added to. */
    private BookmarkDirectory root;
    * Creates a new Bookmarks object, with the entries coming from
    * <code>path</code>.
    public Bookmarks(String path) {
         root = new BookmarkDirectory("Bookmarks");
         if (path != null) {
         parse(path);
    * Returns the root of the bookmarks.
    public BookmarkDirectory getRoot() {
         return root;
    protected void parse(String path) {
         try {
         BufferedReader reader = new BufferedReader(new FileReader
                                       (path));
         new ParserDelegator().parse(reader, new CallbackHandler(), true);
         catch (IOException ioe) {
         System.out.println("IOE: " + ioe);
         JOptionPane.showMessageDialog(null, "Load Bookmarks",
                             "Unable to load bookmarks",
                             JOptionPane.ERROR_MESSAGE);
    private static final short NO_ENTRY = 0;
    private static final short BOOKMARK_ENTRY = 2;
    private static final short DIRECTORY_ENTRY = 3;
    private class CallbackHandler extends HTMLEditorKit.ParserCallback {
         /** Parent node that new entries are added to. */
         private BookmarkDirectory parent;
         /** The most recently parsed tag. */
         private HTML.Tag tag;
         /** The last tag encountered. */
         private HTML.Tag lastTag;
         * The state, will be one of NO_ENTRY, DIRECTORY_ENTRY,
    * or BOOKMARK_ENTRY.
         private short state;
         * Date for the next BookmarkDirectory node.
         private Date parentDate;
         * The values from the attributes are placed in here. When the
         * text is encountered this is added to the node hierarchy and a
    * new instance is created.
         private BookmarkEntry lastBookmark;
         * Creates the CallbackHandler.
         public CallbackHandler() {
         parent = root;
         lastBookmark = new BookmarkEntry();
         // HTMLEditorKit.ParserCallback methods
         * Invoked when text in the html document is encountered. Based on
         * the current state, this will either: do nothing
    * (state == NO_ENTRY),
         * create a new BookmarkEntry (state == BOOKMARK_ENTRY) or
    * create a new
         * BookmarkDirectory (state == DIRECTORY_ENTRY). If state is
    * != NO_ENTRY, it is reset to NO_ENTRY after this is
    * invoked.
    public void handleText(char[] data, int pos) {
         switch (state) {
         case NO_ENTRY:
              break;
         case BOOKMARK_ENTRY:
              // URL.
              lastBookmark.setName(new String(data));
    parent.add(lastBookmark);
    lastBookmark = new BookmarkEntry();
              break;
         case DIRECTORY_ENTRY:
              // directory.
              BookmarkDirectory newParent = new
                   BookmarkDirectory(new String(data));
              newParent.setCreated(parentDate);
              parent.add(newParent);
              parent = newParent;
              break;
         default:
              break;
    state = NO_ENTRY;
         * Invoked when a start tag is encountered. Based on the tag
         * this may update the BookmarkEntry and state, or update the
         * parentDate.
         public void handleStartTag(HTML.Tag t, MutableAttributeSet a,
                        int pos) {
         lastTag = tag;
         tag = t;
         if (t == HTML.Tag.A && lastTag == HTML.Tag.DT) {
    long lDate;
              // URL
              URL url;
              try {
              url = new URL((String)a.getAttribute(HTML.Attribute.HREF));
              } catch (MalformedURLException murle) {
              url = null;
              lastBookmark.setLocation(url);
              // created
              Date date;
              try {
    lDate = Long.parseLong((String)a.getAttribute("add_date"));
    if (lDate != 0l) {
    date = new Date(1000l * lDate);
    else {
    date = null;
              } catch (Exception ex) {
              date = null;
              lastBookmark.setCreated(date);
              // last visited
              try {
    lDate = Long.parseLong((String)a.
    getAttribute("last_visit"));
    if (lDate != 0l) {
    date = new Date(1000l * lDate);
    else {
    date = null;
              } catch (Exception ex) {
              date = null;
              lastBookmark.setLastVisited(date);
              state = BOOKMARK_ENTRY;
         else if (t == HTML.Tag.H3 && lastTag == HTML.Tag.DT) {
              // new node.
              try {
              parentDate = new Date(1000l * Long.parseLong((String)a.
                                  getAttribute("add_date")));
              } catch (Exception ex) {
              parentDate = null;
              state = DIRECTORY_ENTRY;
         * Invoked when the end of a tag is encountered. If the tag is
         * a DL, this will set the node that parents are added to the current
         * nodes parent.
         public void handleEndTag(HTML.Tag t, int pos) {
         if (t == HTML.Tag.DL && parent != null) {
              parent = (BookmarkDirectory)parent.getParent();
    public static class BookmarkDirectory extends DefaultMutableTreeNode {
         /** Dates created. */
         private Date created;
         public BookmarkDirectory(String name) {
         super(name);
         public void setName(String name) {
         setUserObject(name);
         public String getName() {
         return (String)getUserObject();
         public void setCreated(Date date) {
         this.created = date;
         public Date getCreated() {
         return created;
    public static class BookmarkEntry extends DefaultMutableTreeNode {
         /** User description of the string. */
         private String name;
         /** The URL the bookmark represents. */
         private URL location;
         /** Dates the URL was last visited. */
         private Date lastVisited;
         /** Date the URL was created. */
         private Date created;
         public void setName(String name) {
         this.name = name;
         public String getName() {
         return name;
         public void setLocation(URL location) {
         this.location = location;
         public URL getLocation() {
         return location;
         public void setLastVisited(Date date) {
         lastVisited = date;
         public Date getLastVisited() {
         return lastVisited;
         public void setCreated(Date date) {
         this.created = date;
         public Date getCreated() {
         return created;
         public String toString() {
         return getName();
    // Bookmarks.java END
    // BookmarksModel.java BEGIN
    import java.util.Date;
    public class BookmarksModel extends DynamicTreeTableModel {
    * Names of the columns.
    private static final String[] columnNames =
    { "Name", "Location", "Last Visited", "Created" };
    * Method names used to access the data to display.
    private static final String[] methodNames =
    { "getName", "getLocation", "getLastVisited","getCreated" };
    * Method names used to set the data.
    private static final String[] setterMethodNames =
    { "setName", "setLocation", "setLastVisited","setCreated" };
    private static final Class[] classes =
    { TreeTableModel.class, String.class, Date.class, Date.class };
    public BookmarksModel(Bookmarks.BookmarkDirectory root) {
         super(root, columnNames, methodNames, setterMethodNames, classes);
    public boolean isCellEditable(Object node, int column) {
         switch (column) {
         case 0:
         // Allow editing of the name, as long as not the root.
         return (node != getRoot());
         case 1:
         // Allow editing of the location, as long as not a
         // directory
         return (node instanceof Bookmarks.BookmarkEntry);
         default:
         // Don't allow editing of the date fields.
         return false;
    // BookmarksModel.java END
    // DynamicTreeTableModel.java BEGIN
    import java.lang.reflect.*;
    import javax.swing.tree.*;
    public class DynamicTreeTableModel extends AbstractTreeTableModel {
    /** Names of the columns, used for the TableModel getColumnName method. */
    private String[] columnNames;
    private String[] methodNames;
    private String[] setterMethodNames;
    /** Column classes, used for the TableModel method getColumnClass. */
    private Class[] cTypes;
    public DynamicTreeTableModel(TreeNode root, String[] columnNames,
                        String[] getterMethodNames,
                        String[] setterMethodNames,
                        Class[] cTypes) {
         super(root);
         this.columnNames = columnNames;
         this.methodNames = getterMethodNames;
         this.setterMethodNames = setterMethodNames;
         this.cTypes = cTypes;
    public int getChildCount(Object node) {
         return ((TreeNode)node).getChildCount();
    public Object getChild(Object node, int i) {
         return ((TreeNode)node).getChildAt(i);
    public boolean isLeaf(Object node) {
         return ((TreeNode)node).isLeaf();
    public int getColumnCount() {
         return columnNames.length;
    public String getColumnName(int column) {
         if (cTypes == null || column < 0 || column >= cTypes.length) {
         return null;
         return columnNames[column];
    public Class getColumnClass(int column) {
         if (cTypes == null || column < 0 || column >= cTypes.length) {
         return null;
         return cTypes[column];
    public Object getValueAt(Object node, int column) {
         try {
         Method method = node.getClass().getMethod(methodNames[column],
                                  null);
         if (method != null) {
              return method.invoke(node, null);
         catch (Throwable th) {}
         return null;
    * Returns true if there is a setter method name for column
    * <code>column</code>. This is set in the constructor.
    public boolean isCellEditable(Object node, int column) {
    return (setterMethodNames != null &&
         setterMethodNames[column] != null);
    // Note: This looks up the methods each time! This is rather inefficient;
    // it should really be changed to cache matching
    // methods/constructors
    // based on <code>node</code>'s class, and code>aValue</code>'s
    //class.
    public void setValueAt(Object aValue, Object node, int column) {
         boolean found = false;
         try {
         // We have to search through all the methods since the
         // types may not match up.
         Method[] methods = node.getClass().getMethods();
         for (int counter = methods.length - 1; counter >= 0; counter--) {
              if (methods[counter].getName().equals
              (setterMethodNames[column]) && methods[counter].
              getParameterTypes() != null && methods[counter].
              getParameterTypes().length == 1) {
              // We found a matching method
              Class param = methods[counter].getParameterTypes()[0];
              if (!param.isInstance(aValue)) {
                   // Yes, we can use the value passed in directly,
                   // no coercision is necessary!
                   if (aValue instanceof String &&
                   ((String)aValue).length() == 0) {
                   // Assume an empty string is null, this is
                   // probably bogus for here.
                   aValue = null;
                   else {
                   // Have to attempt some sort of coercision.
                   // See if the expected parameter type has
                   // a constructor that takes a String.
                   Constructor cs = param.getConstructor
                   (new Class[] { String.class });
                   if (cs != null) {
                        aValue = cs.newInstance(new Object[]
                                       { aValue });
                   else {
                        aValue = null;
              // null either means it was an empty string, or there
              // was no translation. Could potentially deal with these
              // differently.
              methods[counter].invoke(node, new Object[] { aValue });
              found = true;
              break;
         } catch (Throwable th) {
         System.out.println("exception: " + th);
         if (found) {
         // The value changed, fire an event to notify listeners.
         TreeNode parent = ((TreeNode)node).getParent();
         fireTreeNodesChanged(this, getPathToRoot(parent),
                        new int[] { getIndexOfChild(parent, node) },
                        new Object[] { node });
    public TreeNode[] getPathToRoot(TreeNode aNode) {
    return getPathToRoot(aNode, 0);
    private TreeNode[] getPathToRoot(TreeNode aNode, int depth) {
    TreeNode[] retNodes;
         // This method recurses, traversing towards the root in order
         // size the array. On the way back, it fills in the nodes,
         // starting from the root and working back to the original node.
    /* Check for null, in case someone passed in a null node, or
    they passed in an element that isn't rooted at root. */
    if(aNode == null) {
    if(depth == 0)
    return null;
    else
    retNodes = new TreeNode[depth];
    else {
    depth++;
    if(aNode == root)
    retNodes = new TreeNode[depth];
    else
    retNodes = getPathToRoot(aNode.getParent(), depth);
    retNodes[retNodes.length - depth] = aNode;
    return retNodes;
    // DynamicTreeTableModel.java END
    // IconRenderer.java BEGIN
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.tree.*;
    import javax.swing.plaf.basic.BasicTreeUI;
    class IconRenderer extends DefaultTreeCellRenderer
    // Color backColor = new Color(0xD0, 0xCC, 0xFF);
    Color backColor = new Color(0xF0, 0xF0, 0xE0);
    String tipText = "";
    JTree tree;
    int currRow = 0;
    boolean m_selected;
    JTable table;
    public IconRenderer(JTree tree, JTable table) {
    this.table = table;
    // setBackground(backColor);
    setBackground(Color.GREEN);
    setForeground(Color.black);
         this.tree = tree;
    public Component getTreeCellRendererComponent(JTree tree, Object value,
    boolean selected,
    boolean expanded, boolean leaf,
    int row, boolean hasFocus) {
         Object node = null;
         super.getTreeCellRendererComponent(
    tree, value, selected,
    expanded, leaf, row,
    hasFocus);
         TreePath treePath = tree.getPathForRow(row);
    if(treePath != null)
              node = treePath.getLastPathComponent();
    currRow = row;
    m_selected = selected;
    DefaultMutableTreeNode itc = null;
    if (node instanceof DefaultMutableTreeNode) {
    itc = (DefaultMutableTreeNode)node;
         setClosedIcon(closedIcon);
    setOpenIcon(openIcon);
    return this;
    /* Override the default to send back different strings for folders and leaves. */
    public String getToolTipText() {
    return tipText;
    * Paints the value. The background is filled based on selected.
    public void paint(Graphics g) {
         super.paint(g);
         Color bColor = null;
         if(!m_selected) {
              System.out.println(" iconren not sel currRow " + currRow);
              if(currRow % 2 == 0) {
                   bColor = Color.WHITE;
              } else {
              bColor = backColor;
         } else {
              bColor = table.getSelectionBackground();
              System.out.println("in else selbg = " + bColor);           
              bColor = new Color(0xF0, 0xCC, 0x92);
              System.out.println(" bColor aft = " + bColor);           
         int imageOffset = -1;
         if(bColor != null) {
         imageOffset = getLabelStart();
         g.setColor(bColor);
         if(!m_selected) {
              System.out.println(" not sel setting white ");
              g.setXORMode(new Color(0xFF, 0xFF, 0xFF));
         } else {
    //          g.setXORMode(new Color(0xCC, 0xCC, 0x9F));
              g.setXORMode(new Color(0x00, 0x00, 0x00));
              System.out.println(" using color = " + g.getColor());           
         if(getComponentOrientation().isLeftToRight()) {
         g.fillRect(imageOffset, 0, getWidth() - 1 - imageOffset,
                   getHeight());
         } else {
         g.fillRect(0, 0, getWidth() - 1 - imageOffset,
                   getHeight());
    private int getLabelStart() {
         Icon currentI = getIcon();
         if(currentI != null && getText() != null) {
         return currentI.getIconWidth() + Math.max(0, getIconTextGap() - 1);
         return 0;
    // IconRenderer.java END
    // IndicatorRenderer.java BEGIN
    // import java.awt.*;
    import javax.swing.*;
    import javax.swing.border.*;
    import javax.swing.event.*;
    import javax.swing.tree.*;
    import javax.swing.table.*;
    import javax.swing.table.*;
    import javax.swing.plaf.basic.*;
    import java.awt.event.*;
    import java.util.EventObject;
    import java.text.NumberFormat;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.StringTokenizer;
    import java.util.Arrays;
    class IndicatorRenderer extends DefaultTableCellRenderer {
    /** Makes sure the number of displayed in an internationalized
    * manner. */
    protected NumberFormat formatter;
    /** Row that is currently being painted. */
    protected int lastRow;
    protected int reloadRow;
    protected int reloadCounter;
    protected TreeTableModel treeTableModel;
    protected TreeTableModelAdapter treeTblAdapter;
    protected JTable table;
    Component renderer = null;
    Color backColor = new Color(0xF0, 0xF0, 0xE0);
    IndicatorRenderer(TreeTableModelAdapter treeTblAdapter, TreeTableModel treeTableModel) {
         setHorizontalAlignment(JLabel.RIGHT);
         setFont(new Font("serif", Font.BOLD, 12));
         this.treeTableModel = treeTableModel;
         this.treeTblAdapter = treeTblAdapter;
    * Invoked as part of DefaultTableCellRenderers implemention. Sets
    * the text of the label.
    public void setValue(Object value) {
    /* setText((value == null) ? "---" : formatter.format(value)); */
         setText((value == null) ? "---" : (String) value.toString());
    * Returns this.
    public Component getTableCellRendererComponent(JTable table,
    Object value, boolean isSelected, boolean hasFocus,
    int row, int column) {
         renderer = super.getTableCellRendererComponent(table, value, isSelected,
    hasFocus, row, column);
         lastRow = row;
         this.table = table;
              if(isSelected) {
                   doMask(hasFocus, isSelected);
              } else
              setBackground(table.getBackground());
    return renderer;
    * If the row being painted is also being reloaded this will draw
    * a little indicator.
    public void paint(Graphics g) {
         super.paint(g);
    private void doMask(boolean hasFocus, boolean selected) {
              maskBackground(hasFocus, selected);
    private void maskBackground(boolean hasFocus, boolean selected) {
              Color seed = null;
              seed = table.getSelectionBackground();
              Color color = seed;
              if (color != null) {
                   setBackground(
    new Color(0xF0, 0xCC, 0x92));
    // IndicatorRenderer.java END
    // JTreeTable.java BEGIN
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.border.*;
    import javax.swing.event.*;
    import javax.swing.tree.*;
    import javax.swing.table.*;
    import java.awt.event.*;
    import java.util.EventObject;
    public class JTreeTable extends JTable {
    /** A subclass of JTree. */
    protected TreeTableCellRenderer tree;
    protected IndicatorRenderer indicatorRenderer = null;
    public JTreeTable(TreeTableModel treeTableModel) {
         super();
         // Creates the tree. It will be used as a renderer and editor.
         tree = new TreeTableCellRenderer(treeTableModel);
         TreeTableModelAdapter tdap = new TreeTableModelAdapter(treeTableModel, tree);
         // Installs a tableModel representing the visible rows in the tree.
         super.setModel(tdap);
         // Forces the JTable and JTree to share their row selection models.
         ListToTreeSelectionModelWrapper selectionWrapper = new
         ListToTreeSelectionModelWrapper();
         tree.setSelectionModel(selectionWrapper);
         setSelectionModel(selectionWrapper.getListSelectionModel());
         // Installs the tree editor renderer and editor.
         setDefaultRenderer(TreeTableModel.class, tree);
         setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());
         indicatorRenderer = new IndicatorRenderer(tdap, treeTableModel);     
         // No grid.
         setShowGrid(false);
         // No intercell spacing
         setIntercellSpacing(new Dimension(0, 0));     
         // And update the height of the trees row to match that of
         // the table.
         //if (tree.getRowHeight() < 1) {
         // Metal looks better like this.
         setRowHeight(20);
    public TableCellRenderer getCellRenderer(int row, int col) {
              if(col == 0)
              return tree;
              else
              return indicatorRenderer;     
    public void updateUI() {
         super.updateUI();
         if(tree != null) {
         tree.updateUI();
         // Do this so that the editor is referencing the current renderer
         // from the tree. The renderer can potentially change each time
         // laf changes.
         setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());
         // Use the tree's default foreground and background colors in the
         // table.
    LookAndFeel.installColorsAndFont(this, "Tree.background",
    "Tree.foreground", "Tree.font");
    public int getEditingRow() {
    return (getColumnClass(editingColumn) == TreeTableModel.class) ? -1 :
         editingRow;
    private int realEditingRow() {
         return editingRow;
    public void sizeColumnsToFit(int resizingColumn) {
         super.sizeColumnsToFit(resizingColumn);
         if (getEditingColumn() != -1 && getColumnClass(editingColumn) ==
         TreeTableModel.class) {
         Rectangle cellRect = getCellRect(realEditingRow(),
                             getEditingColumn(), false);
    Component component = getEditorComponent();
         component.setBounds(cellRect);
    component.validate();
    public void setRowHeight(int rowHeight) {
    super.setRowHeight(rowHeight);
         if (tree != null && tree.getRowHeight() != rowHeight) {
    tree.setRowHeight(getRowHeight());
    public JTree getTree() {
         return tree;
    public boolean editCellAt(int row, int column, EventObject e){
         boolean retValue = super.editCellAt(row, column, e);
         if (retValue && getColumnClass(column) == TreeTableModel.class) {
         repaint(getCellRect(row, column, false));
         return retValue;
    public class TreeTableCellRenderer extends JTree implements
         TableCellRenderer {
         /** Last table/tree row asked to renderer. */
         protected int visibleRow;
         /** Border to draw around the tree, if this is non-null, it will
         * be painted. */
         protected Border highlightBorder;
         public TreeTableCellRenderer(Tr

  • '...' not appearing in obscured table cell when using custom renderer.

    Hello all -
    I am using a custom JPanel as a cell renderer in a JTable to display two icons per cell. Unfortunately, I am running into a problem that occurs when resizing a column such that the width of the column is less than the size of the cell content. Normally, when resizing a cell in this manner, it will start to cut off the text within the cell and add '...' to signify that some material is obscured. However, using my cell renderer, the text simply cuts off with no indication whatsoever there is more content that is being hidden. I have tried looking through the JComponent code to find a function to overload but I haven't had much luck. Does anyone have any suggestions?
    For a simple example, compile and run the following code and try resizing the two columns. You should be able to notice the difference.
    Thanks,
    - Alex
    import java.awt.*;
    import java.awt.image.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.table.*;
    public class TwoIcons extends JFrame {
         public static void main(String[] args){
              createIcons();
              SwingUtilities.invokeLater
                   new Runnable()
                        public void run() {
                             new TwoIcons();
         public TwoIcons(){
              super("Test");
              DefaultTableModel tm = new DefaultTableModel(
                   new Object[][]{
                        {new IconPair("cross", "cross"), "just a string"},
                        {new IconPair("circle", "cross"),"just another string"},
                        {new IconPair("String", "circle"),"yet another string"}
                   }, new String[]{"Two Icons","String"}){
                   public Class getColumnClass(int columnIndex){
                        if(columnIndex==0){
                             return IconPair.class;
                        else
                             return super.getColumnClass(columnIndex);
              JTable table = new JTable(tm);
              final Color bg = table.getBackground();
              table.setDefaultRenderer(IconPair.class, new TableCellRenderer(){
                        RendererPanel renderer = new RendererPanel(bg);
                        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                             renderer.setIcons((IconPair)value);
                             return  renderer;
              JScrollPane scp = new JScrollPane(table);
              add(scp);
              setSize(400,100);
              setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              pack();
              setVisible(true);
         class RendererPanel extends JPanel{
              JLabel icon1, icon2;
              RendererPanel(Color bg){
                   setLayout(new BoxLayout(this,BoxLayout.LINE_AXIS) );
                   icon1=new JLabel();
                   icon2=new JLabel();
                   add(icon1);
                   add(icon2);
                   setBackground(bg);
              public void setIcons(IconPair value) {
                   icon1.setIcon(value.i1);
                   icon1.setToolTipText("Icon 1");
                   icon2.setIcon(value.i2);
                   icon2.setToolTipText("Icon 2");
                   //uncomment next 2 lines if you want text as well
                   icon1.setText(value.s1);
                   icon2.setText(value.s2);
         class IconPair {
              public Icon i1,i2;
              public String s1,s2;
              IconPair(String s1, String s2){
                   this.i1=(Icon)icons.get(s1);
                   this.i2=(Icon)icons.get(s2);
                   this.s1=s1;
                   this.s2=s2;
         static Map icons = new HashMap();
         public static  void createIcons(){
              Image img = new BufferedImage(10,10, BufferedImage.TYPE_INT_ARGB);
              Graphics2D g2=(Graphics2D)(img.getGraphics());
              g2.setColor(Color.BLUE);
              g2.drawLine(0,0,10,10);
              g2.drawLine(0,10,10,0);
              icons.put("cross",new ImageIcon(img));
              img = new BufferedImage(10,10, BufferedImage.TYPE_INT_ARGB);
              g2=(Graphics2D)(img.getGraphics());
              g2.setColor(Color.ORANGE);
              g2.drawOval(1,1,8,8);
              icons.put("circle",new ImageIcon(img));
    }

    Things aren't resizable in your layout for the custom renderer. Here's your code working as you want (I think)
    import java.awt.*;
    import java.awt.image.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.table.*;
    public class TwoIcons extends JFrame {
         public static void main(String[] args){
              createIcons();
              SwingUtilities.invokeLater
                   new Runnable()
                        public void run() {
                             new TwoIcons();
         public TwoIcons(){
              super("Test");
              DefaultTableModel tm = new DefaultTableModel(
                   new Object[][]{
                        {new IconPair("cross", "cross"), "just a string"},
                        {new IconPair("circle", "cross"),"just another string"},
                        {new IconPair("String", "circle"),"yet another string"}
                   }, new String[]{"Two Icons","String"}){
                   public Class getColumnClass(int columnIndex){
                        if(columnIndex==0){
                             return IconPair.class;
                        else
                             return super.getColumnClass(columnIndex);
              JTable table = new JTable(tm);
              final Color bg = table.getBackground();
              table.setDefaultRenderer(IconPair.class, new TableCellRenderer(){
                        RendererPanel renderer = new RendererPanel(bg);
                        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                             renderer.setIcons((IconPair)value);
                             return  renderer;
              JScrollPane scp = new JScrollPane(table);
              getContentPane().add(scp);
              setSize(400,100);
              setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              pack();
              setVisible(true);
         class RendererPanel extends JPanel{
              JLabel icon1, icon2;
              RendererPanel(Color bg){
                   setLayout(new BoxLayout(this,BoxLayout.LINE_AXIS) );
                   icon1=new JLabel();
                   icon2=new JLabel();
                   add(icon1);
                   add(icon2);
                   icon1.setMinimumSize(new Dimension(0, 0));
                   icon2.setMinimumSize(new Dimension(0, 0));
                   icon1.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
                   icon2.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
                   setBackground(bg);
              public void setIcons(IconPair value) {
                   icon1.setIcon(value.i1);
                   icon1.setToolTipText("Icon 1");
                   icon2.setIcon(value.i2);
                   icon2.setToolTipText("Icon 2");
                   //uncomment next 2 lines if you want text as well
                   icon1.setText(value.s1);
                   icon2.setText(value.s2);
         class IconPair {
              public Icon i1,i2;
              public String s1,s2;
              IconPair(String s1, String s2){
                   this.i1=(Icon)icons.get(s1);
                   this.i2=(Icon)icons.get(s2);
                   this.s1=s1;
                   this.s2=s2;
         static Map icons = new HashMap();
         public static  void createIcons(){
              Image img = new BufferedImage(10,10, BufferedImage.TYPE_INT_ARGB);
              Graphics2D g2=(Graphics2D)(img.getGraphics());
              g2.setColor(Color.BLUE);
              g2.drawLine(0,0,10,10);
              g2.drawLine(0,10,10,0);
              icons.put("cross",new ImageIcon(img));
              img = new BufferedImage(10,10, BufferedImage.TYPE_INT_ARGB);
              g2=(Graphics2D)(img.getGraphics());
              g2.setColor(Color.ORANGE);
              g2.drawOval(1,1,8,8);
              icons.put("circle",new ImageIcon(img));
    }Note that the ... is a function of the JLabel when it is too small to render its text.

  • Adding a custom rendering extension to SQL Server Reporting Services 2012 for SharePoint 2010 integrated mode

    We are attempting to add OfficeWriter report rendering extensions for SSRS 2012 in SharePoint (2010) integrated mode through powershell. The documentation for “New-SPRSExtension” is rather
    sparse and we have not found any clear examples on the internet. With SSRS 2012 in native mode, we make the following two changes to the config files:
    We add the following report rendering extension declaration to
    RSReportServer.config:
    <Configuration>
        <Extensions>
            <Render>
                <Extension Name="XLTemplate" Type="SoftArtisans.OfficeWriter.ReportingServices.ExcelTemplateRenderer,
    SoftArtisans.OfficeWriter.RS2008"/>
                <Extension Name="WordTemplate" Type="SoftArtisans.OfficeWriter.ReportingServices.WordTemplateRenderer,
    SoftArtisans.OfficeWriter.RS2008"/>
            </Render>
        </Extensions>
    </Configuration>
    We add the following security trust codegroup to
    RSSvrPolicy.config:
    <configuration>
        <mscorlib>
            <security>
                <policy>
                    <PolicyLevel version="1">
                  <CodeGroup version="1" PermissionSetName="Nothing">
                    <CodeGroup
                                version="*"
                                PermissionSetName="FullTrust"
                                Name="SoftArtisans_OfficeWriter_Strong_Name"
                                Description="This
    code group grants SoftArtisans OfficeWriter code full trust.">
                              <IMembershipCondition
                                class="StrongNameMembershipCondition"
                                version="*"
                                PublicKeyBlob="00240000048000009400000006020000002400005253413100040000010001004779CB207F11
                                5E86EF9DD3233F9F130F8891911345176650F72330F84CA3F54C96DEB08439680660F02872EEF5DA3955
                                A14C63F96E57DFB71B1535280C37DA2CB5BA37D78A9882414DB11F67FD66DEBC4AD93DD34F4A587D34D
                                B4D23D9C6AF83431D88A7EF42BB01082913F3560DCB50129C5BBA7ECA0DE8BC286DA74F58FADE"/>
                  </CodeGroup>
              </CodeGroup>
           </PolicyLevel>
        </policy>
       </security>
      </mscorlib>
    </configuration>
    What would be the equivalent syntax for “New-SPRSExtension” to do the above for SSRS 2012 in SharePoint (2010) integrated mode?
    Alison Bird SoftArtisans Technical Services www.softartisans.com

    Hi Alison,
    Unlike the deployment of other custom extensions such as custom delivery extension and data processing extension, it is not necessary to add a code group for the custom assembly that grants FullTrust permission for the extension during the deployment of
    custom rendering extension. If you have copy the custom assembly to the %ProgramFiles%\Microsoft SQL Server\MSRS11.<InstanceName>\Reporting Services\ReportServer\Bin folder, and modify the RSreportserver.config file to add the extention entry properly,
    please open the SSRS Service Application created on the SharePoint and verify that your extension is included in the list of available export types for a report.
    Reference:
    Deploying a Rendering Extension
    Regards,
    Mike Yin
    TechNet Community Support

Maybe you are looking for

  • Watch Ipod Classice on TV

    I bought a component AV cable for my Ipod/tv. When I hooked it up, the sound comes through but the picture does not come through (there are lines on the screen). Does anyone know why? I have checked the cable connections multiple times, but no change

  • Pictures lost in ipod

    I spent a few days in Athens and took about 300 pictures. I transferred them with the camera connector on my 20Go ipod (bought in august). Of course, I erased the compact flash. And then, while trying to transfer them to my ibook: 200 pictures lost.

  • I reinstalled Photoshop Elements 6 and...

    ...My brushes changed. Not one's I'd downloaded before, but the one's you originally get with it. When it was one my old laptop, I used the 2nd In the Deafult Brushes, and I used it for rough sketches AND lining, and it always came out something like

  • Navigation from ContentDialog in WP 8.1?

    Hi! I made a ContentDialog control to let the user type something... Now I need to pass the typed text into a page. The normal way of doing it (aka. from one page to another) is as follows; Frame.Navigate(typeof(PageName), Parameter); This, however,

  • Cant install itunes 10.6

    get error when tyring to install itunes 10.6 (latest). also get error when trying to install apple mobile divice support. Is  apple mobile divice support the problem?