Multiline TableHeader

This forum is used by users to request and discuss new product features. Please do not use this forum for technical support including bug reports.

Moderator: JIDE Support

Forum rules
Product suggestions only. Please do not use this forum for technical support including bug reports.

Multiline TableHeader

Postby rhk » Thu Jul 28, 2005 6:32 am

Hello Jide's,

I've played a little bit with the JTable's Header components, cause I don't like that "..." if the column gets smaller.

I want to have the text wrapped into more than one lines, if one line doesn't fit the table columns width. I've tried many things (LinebreakMeasurer, creating new Renderer, overwriting JTableHeader)... Some works, but there is a real big bug in Sun's JTable implementation:

Maybe you have specified your own Renderer in JTableHeader.
Then you have put this JTable into a Scrollpane (with JTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF))
Now you drag a columnwidth so that the sum width of all columns is greater than the scrollpane.
If you now scroll to the right, the Header is not exactly repainted....

So this all fails...

Do you have another possibility or can you make a solution to show multiline headers???

Would be great!

Greetings,
Robert
rhk
 
Posts: 35
Joined: Wed May 05, 2004 12:50 am

Postby JIDE Support » Thu Jul 28, 2005 8:58 am

I am aware of the bug you mentioned. We have a multi-line implementation. It is actually used before in SortableTable. Recently we truned it off because we want to keep the XP style table header. Our implementation doesn't keep XP style. There is another customer asking for this too. So in next release we will move it to JideTable level and off by default. Just one method call can turn in on. However it doesn't wrap automatically. You have to put \n in the column name to split lines. Is it good enough for you?

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Postby rhk » Thu Jul 28, 2005 9:07 am

Well... it is good to have this method to switch it on.

Maybe you can introduce a enum for this:

HEADER_WRAP_OFF
HEADER_WRAP_NEWLINE
HEADER_WRAP_AUTOMATICALLY

Our customer is asking for this feature, cause our table can have many columns and he want to resize the columns and like to have an automatical wrap (like that if you add this "<html>" before the label's text property)...

So with the enum one could customize the behavior of the header wrapping to either off, wrapping at the \n or wrapping automatically...

What do you think?

r.
rhk
 
Posts: 35
Joined: Wed May 05, 2004 12:50 am

Postby therodet » Fri Jul 13, 2007 7:36 am

Has this or some other method for a multiline header been implemented? I tried setting the header renderer to a MultilineTableCellRenderer, and the text does wrap, but it doesn't look very good; the cells are plain formatted like table cells, and the header row is sized much taller than it needs to be.
therodet
 
Posts: 37
Joined: Fri Dec 02, 2005 6:52 am
Location: Lansing, MI, US

Postby JIDE Support » Fri Jul 13, 2007 7:43 am

MultilineTableCellRenderer is for table cells, not for table header. As you can read from the posts above, we currently don't have a nice way to wrap header. The only way right way is to use SortTableHeaderRenderer. You can see how to enable it at the javadoc of setSortTableHeaderRenderer of JideTable.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Postby therodet » Fri Jul 13, 2007 8:12 am

Not the prettiest solution, but it does do what I wanted. Thank you for the prompt reply.
therodet
 
Posts: 37
Joined: Fri Dec 02, 2005 6:52 am
Location: Lansing, MI, US

Postby JIDE Support » Fri Jul 13, 2007 8:16 am

I certainly agree. That's why I said we don't have a nice way.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Postby ravipathak » Mon Jul 16, 2007 5:50 am

We achieved the multiline feature by having our header renderer extends JTextArea. The only problem is that the look is not XPStyle, but we need it to "multline" on its own as in a multi lingual scenario we wouldnt know where exactly to put the "\n" in the properties file.
This feature should ideally be provided by Sun itself.
ravipathak
 
Posts: 155
Joined: Thu Jul 06, 2006 5:44 am

Re: Multiline TableHeader

Postby mgs » Mon Dec 01, 2008 11:17 am

HI,
I am new to JIDE and I am also having problem enabling the multi-line header. I tried the setSortTableHeaderRenderer as as shown in the code below. This code works fine but not until I enable the Filter. What I figured out from reading the doc is that the AutoFilterTableHeader creates a new FilterableTableModel and then resets the actual table model with the new FilterableTableModel. How do I tell AutoFilterTableHeader that I want multi-line header. Basically, it should treat a "\n" in the column name as new line.

Code: Select all
protected void initTable() {
            super.initTable();
            setSortTableHeaderRenderer();
         }
         
         protected JTableHeader createDefaultTableHeader() {
               return new JTableHeader(columnModel);
           }
}


Thanks.
mgs
 
Posts: 48
Joined: Mon Dec 01, 2008 11:01 am

Re: Multiline TableHeader

Postby JIDE Support » Mon Dec 01, 2008 11:18 am

Unfortunately it is not possible with both multiple line and auto-filter features.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: Multiline TableHeader

Postby mgs » Mon Dec 01, 2008 1:34 pm

That is unfortunate. Our product heavily uses multi-line header and being able to suport is essential. Is there a way to set the Header Renderer in Auto-Filter?
mgs
 
Posts: 48
Joined: Mon Dec 01, 2008 11:01 am

Re: Multiline TableHeader

Postby JIDE Support » Mon Dec 01, 2008 1:48 pm

It will require quite an effort to get it working. Let me know if you are willing to sponsor such an effort through a custom contract.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: Multiline TableHeader

Postby infn » Thu Jun 04, 2009 1:30 am

Hi,

Will this feature work with sortable table if override initTable() and call setSortTableHeaderRenderer()?
I tried this with SortableTable. It is not working.

Let me know if we can have multi line sortable table.
infn
 
Posts: 333
Joined: Thu Jun 14, 2007 9:41 pm

Re: Multiline TableHeader

Postby infn » Thu Jun 04, 2009 9:09 pm

Is anybody there..???
infn
 
Posts: 333
Joined: Thu Jun 14, 2007 9:41 pm

Re: Multiline TableHeader

Postby JIDE Support » Thu Jun 04, 2009 9:16 pm

Sorry for the late reply. I don't think it will work as AutoFilterTableHeader doesn't take the renderer you set. I wonder if you can use html code to do the multilione text as we are using JLabel inside AutoFilterBox.
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: Multiline TableHeader

Postby infn » Thu Jun 04, 2009 9:41 pm

I tried using HTML text. But there are some problems in setting columns heights for the headers.
Also the text is not rendered properly. When I click on the column header the text moves on top and on mouse release it comes back to normal position.
infn
 
Posts: 333
Joined: Thu Jun 14, 2007 9:41 pm

Re: Multiline TableHeader

Postby JIDE Support » Fri Jun 05, 2009 3:04 pm

Please try the following code to set the height for the table header. I tried it in our SortableTableDemo.

Code: Select all
        _sortableTable.getTableHeader().setPreferredSize(new Dimension(_sortableTable.getTableHeader().getPreferredSize().width, 40));


You probably also need override the cell editor of the table header just like you did to the renderer. Once you click the header, it will enter edit mode automatically.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: Multiline TableHeader

Postby infn » Mon Jun 08, 2009 5:04 am

Hi,

As per my earlier reply to set HTML text to table header I haven;t overridden any renderer. Please let me know the renderer and editor class that I have to set to get it working with sortable table. The table header get distorted in I move my scrollbars and move my mouse over the header.

Thanks & Regards
infn
 
Posts: 333
Joined: Thu Jun 14, 2007 9:41 pm

Re: Multiline TableHeader

Postby JIDE Support » Mon Jun 08, 2009 8:54 am

I could not notice the renderer issue while mouse over the header. Below is my test case FYI.

Code: Select all
/*
 * @(#)SortableTableDemo.java
 *
 * Copyright 2002 - 2003 JIDE Software Inc. All rights reserved.
 */

import com.jidesoft.converter.ConverterContext;
import com.jidesoft.converter.DoubleConverter;
import com.jidesoft.converter.ObjectConverterManager;
import com.jidesoft.grid.*;
import com.jidesoft.hssf.HssfTableUtils;
import com.jidesoft.icons.JideIconsFactory;
import com.jidesoft.plaf.LookAndFeelFactory;
import com.jidesoft.swing.JideBoxLayout;
import com.jidesoft.swing.JideTabbedPane;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * Demoed Component: {@link SortableTable} <br> Required jar files: jide-common.jar, jide-grids.jar <br> Required L&F:
 * any L&F
 */
public class SortableTableDemo extends AbstractDemo {
    protected SortableTable _sortableTable;
    protected String _lastDirectory = ".";
    private static final long serialVersionUID = -5373007282200581748L;

    public SortableTableDemo() {
        ObjectConverterManager.initDefaultConverter();
        DecimalFormat format = new DecimalFormat();
        format.setMinimumFractionDigits(2);
        format.setMaximumFractionDigits(10);
        DoubleConverter converter = new DoubleConverter(format);
        ObjectConverterManager.registerConverter(Double.class, converter);
    }

    public String getName() {
        return "SortableTable Demo";
    }

    public String getProduct() {
        return PRODUCT_NAME_GRIDS;
    }

    @Override
    public int getAttributes() {
        return Demo.ATTRIBUTE_UPDATED;
    }

    @Override
    public String getDescription() {
        return "This is a demo of SortableTable. \n" +
                "\nClick once on the header to sort ascending, click twice to sort descending, a third time to unsort. Hold CTRL key (or Command key on Mac OS X) then click on several headers to see mulitple columns sorting.\n" +
                "\n" +
                "Demoed classes:\n" +
                "com.jidesoft.grid.SortableTable";
    }

    @Override
    public Component getOptionsPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new JideBoxLayout(panel, JideBoxLayout.Y_AXIS));

        panel.add(new JLabel("Maximum sorted columns: "));
        DefaultComboBoxModel model = new DefaultComboBoxModel();
        model.addElement("No maximum (default)");
        for (int i = 0; i < _sortableTable.getColumnCount(); i++) {
            model.addElement(new Integer(i + 1));
        }
        panel.add(Box.createVerticalStrut(3));
        final JComboBox maxComboBox = new JComboBox(model);
        maxComboBox.addActionListener(new AbstractAction() {
            private static final long serialVersionUID = -6480174819379988040L;

            public void actionPerformed(ActionEvent e) {
                int maxCount = maxComboBox.getSelectedIndex();
                if (maxCount == 0) {
                    ((ISortableTableModel) _sortableTable.getModel()).setMaximumSortColumns(-1);
                }
                else {
                    ((ISortableTableModel) _sortableTable.getModel()).setMaximumSortColumns(maxCount);
                }
            }
        });
        panel.add(maxComboBox);

        panel.add(Box.createVerticalStrut(6));

        panel.add(new JLabel("Sort priority: "));
        model = new DefaultComboBoxModel();
        model.addElement("FILO (Default)");
        model.addElement("FIFO");
        panel.add(Box.createVerticalStrut(3));
        final JComboBox priorityComboBox = new JComboBox(model);
        priorityComboBox.addActionListener(new AbstractAction() {
            private static final long serialVersionUID = 3712678830602409607L;

            public void actionPerformed(ActionEvent e) {
                int priority = priorityComboBox.getSelectedIndex();
                ((ISortableTableModel) _sortableTable.getModel()).setSortPriority(priority);
            }
        });
        panel.add(priorityComboBox);

        panel.add(Box.createVerticalStrut(12));

        JCheckBox sortingEnabled = new JCheckBox("Allow user to sort table");
        sortingEnabled.setSelected(_sortableTable.isSortingEnabled());
        sortingEnabled.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                _sortableTable.setSortingEnabled(e.getStateChange() == ItemEvent.SELECTED);
            }
        });
        panel.add(sortingEnabled);

        JCheckBox showSortOrder = new JCheckBox("Always show sort order");
        showSortOrder.setSelected(_sortableTable.isShowSortOrderNumber());
        showSortOrder.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                _sortableTable.setShowSortOrderNumber(e.getStateChange() == ItemEvent.SELECTED);
            }
        });
        panel.add(showSortOrder);

        final JCheckBox sortIconCheckBox = new JCheckBox("Use Look&Feel Default Sort Icon");
        sortIconCheckBox.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                _sortableTable.setUseLnfDefaultSortIcon(e.getStateChange() == ItemEvent.SELECTED);
            }
        });
        sortIconCheckBox.setSelected(_sortableTable.isUseLnfDefaultSortIcon());
        panel.add(sortIconCheckBox);

        panel.add(Box.createVerticalStrut(12));

        panel.add(new JButton(new AbstractAction("Export to Excel") {
            private static final long serialVersionUID = -3816637828684822007L;

            public void actionPerformed(ActionEvent e) {
                if (!HssfTableUtils.isHssfInstalled()) {
                    JOptionPane.showMessageDialog((Component) e.getSource(), "Export to Excel feature is disabled in the webstart demo because hssf.jar is not in the classpath.");
                    return;
                }
                JFileChooser chooser = new JFileChooser() {
                    @Override
                    protected JDialog createDialog(Component parent) throws HeadlessException {
                        JDialog dialog = super.createDialog(parent);
                        dialog.setTitle("Export the content to an \".xls\" file");
                        return dialog;
                    }
                };
                chooser.setCurrentDirectory(new File(_lastDirectory));
                int result = chooser.showDialog(((JButton) e.getSource()).getTopLevelAncestor(), "Export");
                if (result == JFileChooser.APPROVE_OPTION) {
                    _lastDirectory = chooser.getCurrentDirectory().getAbsolutePath();
                    try {
                        HssfTableUtils.export(_sortableTable, chooser.getSelectedFile().getAbsolutePath(), "SortableTable", false, true, new HssfTableUtils.DefaultCellValueConverter() {
                            @Override
                            public int getDataFormat(JTable table, Object value, int rowIndex, int columnIndex) {
                                if (value instanceof Double) {
                                    return 2; // use 0.00 format
                                }
                                else if (value instanceof Date) {
                                    return 0xe; // use "m/d/yy" format
                                }
                                return super.getDataFormat(table, value, rowIndex, columnIndex);
                            }
                        });
                    }
                    catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
            }
        }));
        return panel;
    }

    public Component getDemoPanel() {
        TableModel model = new SampleTableModel();

        _sortableTable = new SortableTable(model);
        AutoFilterTableHeader header = new AutoFilterTableHeader(_sortableTable);
        header.setAutoFilterEnabled(true);
        _sortableTable.setTableHeader(header);
        _sortableTable.getTableHeader().setPreferredSize(new Dimension(_sortableTable.getTableHeader().getPreferredSize().width, 40));

        JTable normalTable = new JTable(model);

        JideTabbedPane tabbedPane = new JideTabbedPane();
        tabbedPane.setTabShape(JideTabbedPane.SHAPE_BOX);
        tabbedPane.addTab("SortableTable", new JScrollPane(_sortableTable));
        tabbedPane.addTab("JTable (for comparison)", new JScrollPane(normalTable));
        tabbedPane.setPreferredSize(new Dimension(550, 400));
        return tabbedPane;
    }

    static class SampleTableModel extends AbstractTableModel implements ContextSensitiveTableModel, ToolTipSupport {
        private static final long serialVersionUID = 8798261997256893224L;

        public int getColumnCount() {
            return 6;
        }

        public int getRowCount() {
            return 8;
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return false;
        }

        public ConverterContext getConverterContextAt(int row, int column) {
            return null;
        }

        public EditorContext getEditorContextAt(int row, int column) {
            return null;
        }

        public Class<?> getCellClassAt(int row, int column) {
            return getColumnClass(column);
        }

        @Override
        public String getColumnName(int column) {
            switch (column) {
                case 0:
                    return "int column";
                case 1:
                    return "<html>double<br>column</html>";
                case 2:
                    return "boolean column";
                case 3:
                    return "string column";
                case 4:
                    return "icon column";
                case 5:
                    return "date column";
            }
            return "";
        }

        @Override
        public Class<?> getColumnClass(int column) {
            switch (column) {
                case 0:
                    return Integer.class;
                case 1:
                    return Double.class;
                case 2:
                    return Boolean.class;
                case 3:
                    return String.class;
                case 4:
                    return Icon.class;
                case 5:
                    return Date.class;
            }
            return Object.class;
        }

        public Object getValueAt(int row, int column) {
            switch (column) {
                case 0:
                    if (row > 4) {
                        return 2;
                    }
                    else {
                        return row;
                    }
                case 1:
                    return row * 2.333333;
                case 2:
                    if (row % 2 == 0)
                        return Boolean.TRUE;
                    return Boolean.FALSE;
                case 3:
                    return "row " + (getRowCount() - row);
                case 4:
                    if (row % 2 == 0)
                        return JideIconsFactory.getImageIcon(JideIconsFactory.FileType.HTML);
                    else
                        return JideIconsFactory.getImageIcon(JideIconsFactory.FileType.JAVA);
                case 5:
                    Calendar calendar = Calendar.getInstance();
                    calendar.roll(Calendar.DAY_OF_YEAR, row);
                    return calendar.getTime();
            }
            return null;
        }

        public String getToolTipText(int columnIndex) {
            return "Click to sort this " + getColumnName(columnIndex);
        }
    }

    @Override
    public String getDemoFolder() {
        return "G2.SortableTable";
    }

    static public void main(String[] s) {
        LookAndFeelFactory.installDefaultLookAndFeelAndExtension();
        showAsFrame(new SortableTableDemo());
    }
}


Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: Multiline TableHeader

Postby mgs » Mon Jun 08, 2009 9:58 am

Hi infn,
I am also using MultiLine table header. I tried several options and what I found working is using Cell renderer that format the Header. However, when you enable the Filter it will not use the renderer that you set so you will have to override the customizeAutoFilterBox to format the header.

Below is the sample code. It will not compile right away as I just cut and pasted it from my code. Just remove irrelevant stuff. I hope this gives you some idea.


AutoFilterTableHeader
Code: Select all
import javax.swing.Icon;
import javax.swing.JTable;
import javax.swing.table.TableModel;
import java.util.Comparator;

import com.jidesoft.grid.AutoFilterBox;
import com.jidesoft.grid.AutoFilterTableHeader;
import com.jidesoft.grid.FilterableTableModel;
import com.jidesoft.grid.FilterableTableModelEvent;
import com.jidesoft.grid.FilterableTreeTableModel;
import com.jidesoft.grid.IFilterableTableModel;
import com.jidesoft.grid.SortableTable;
import com.jidesoft.grid.TreeTable;

public class CNAutoFilterTableHeader extends AutoFilterTableHeader
{
   private JTable _table = null;
   private CNTablePanel _nTable = null;
   
   public CNAutoFilterTableHeader(CNTablePanel nTable)
   {
      super(nTable.getTable());
      _table = nTable.getTable();
      _nTable = nTable;
      
   }
   
   
   
   @Override
    protected IFilterableTableModel createFilterableTableModel(TableModel model) {
      if (_table instanceof TreeTable)
      {
           return new FilterableTableModel(model) {
               @Override
               public boolean isColumnAutoFilterable(int column) {
                   return true;
               }
               @Override
            public Object[] getPossibleValues(int column, Comparator comparator) {
                   return super.getPossibleValues(column, new Comparator(){
                  public int compare(Object firstObj, Object secondObj) {
                           try {
                              if (firstObj instanceof Comparable && secondObj instanceof Comparable)
                              {
                                 return ((Comparable)firstObj).compareTo(secondObj);
                              }
                                else {
                                   String str1 = firstObj.toString();
                                   String str2 = secondObj.toString();
                                   return (str1.compareToIgnoreCase(str2));
                               }
                           } catch (Exception e) {
                               e.printStackTrace();
                               return -1;
                           }
                       }
                   });
               }
               @Override
            protected boolean shouldPossibleValueBeIncluded(Object value,int columnIndex)
            {
               if (value == null)
                  return false;
               
               return !(value.toString().equals(""));
            }
              
              
              
           };
      }
      else
      {
          return new FilterableTreeTableModel(model) {
                  @Override
                  public boolean isColumnAutoFilterable(int column) {
                      return true;
                  }
                  @Override
               public Object[] getPossibleValues(int column, Comparator comparator) {
                      return super.getPossibleValues(column, new Comparator(){
                     public int compare(Object firstObj, Object secondObj) {
                              try {
                                 if (firstObj instanceof Comparable && secondObj instanceof Comparable)
                                 {
                                    return ((Comparable)firstObj).compareTo(secondObj);
                                 }
                                   else {
                                      String str1 = firstObj.toString();
                                      String str2 = secondObj.toString();
                                      return (str1.compareToIgnoreCase(str2));
                                  }
                              } catch (Exception e) {
                                  e.printStackTrace();
                                  return -1;
                              }
                          }
                     
                      });
                  }
                  @Override
               protected boolean shouldPossibleValueBeIncluded(Object value,int columnIndex)
               {
                  if (value == null)
                     return false;
                  
                  if (value instanceof JobStatus )
                  {
                     String str = ((JobStatus)value).toString();
                     if (str.equals(StringBank.UNKNOWN))
                        return false;
                     else
                        return!(str.equals(""));
                  }
                     
                  return !(value.toString().equals(""));
               }
                 
              };
      }
    }
   
    @Override
     public void filterableTableModelChanged(FilterableTableModelEvent event)
     {
       super.filterableTableModelChanged(event);
       _nTable.setPreferredWidthOfColumns();
     }
   
   protected void customizeAutoFilterBox(AutoFilterBox autoFilterBox) {
      autoFilterBox.setBackground(Utilities.COLOR_LIGHT_LIGHT_GREY);
      if (autoFilterBox.getFilterTitleFormatter() ==null) {                
         autoFilterBox.setFilterTitleFormatter(new Formatter());
      }
      super.customizeAutoFilterBox(autoFilterBox);
      autoFilterBox.setShowFilterName(true);     
      
   }
   
   protected Icon createSortIcon(SortableTable table, boolean ascending)
     {
        if (ascending)
           return RuntimeContext.upIcon;
        else
           return RuntimeContext.downIcon;
     }
   
   class Formatter implements  AutoFilterBox.FilterTitleFormatter
    {
       String filter = "";
       public String formatColumnTitle(String columnName, com.jidesoft.filter.Filter[] filters) {
          filter = "";
         if (filters !=null && filters.length > 0)
         {
            if ( filters[0].getName().equals("All") == false)
               filter = ":" + filters[0].getName();
         }
            
      //   System.out.println("formatColumnTitle:: " + columnName + ", filter: " + filter);
         return "<html><body><b>" + columnName + filter +  "</b></body></html>";
      }
       
       public String getFilterName()
       {
          return filter;
       }
       public void clearFilter()
       {
          filter="";
       }
    }
          
}


RENDERER
Code: Select all

  public static class CNTableHeaderRenderer extends DefaultTableCellRenderer
    {
        GradientPanel panel = null;
       int maxHeight = 0; 
       int pady = 10;
         
       public CNTableHeaderRenderer(boolean darkHeader)
       {
          if (darkHeader)
             panel = new GradientPanel(new GridBagLayout(),  Utilities.COLOR_GRADIENT1_DARKER, Utilities.COLOR_GRADIENT2, GradientPanel.VERTICAL);
          else
             panel = new GradientPanel(new GridBagLayout(), Utilities.COLOR_GRADIENT2, GradientPanel.VERTICAL);
       }
       
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
          Component actualRenderer = super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column);
          
           if (table != null) {
               JTableHeader header = table.getTableHeader();
               if (header != null) {
                   actualRenderer.setForeground(header.getForeground());
                    actualRenderer.setBackground(header.getBackground());
                   actualRenderer.setFont(header.getFont().deriveFont(Font.BOLD));
                   }
            }
          
            Component headerComponent = null;
            String stringValue = (value == null) ? "" : value.toString();
            GridBagConstraints constraints = new GridBagConstraints();
             if (stringValue.indexOf('\n') != -1)
            {
               
               JPanel cellPanel =new JPanel(new GridBagLayout());
               cellPanel.setOpaque(false);
                constraints = new GridBagConstraints();
                String totalString = stringValue;
                JLabel tempLabel = null;
                int rows =0;
                while(totalString.indexOf('\n') != -1)
                {
                    String partString = totalString.substring(0, totalString.indexOf('\n'));
                    tempLabel = new JLabel(partString);
                    tempLabel.setHorizontalAlignment(JLabel.CENTER);
                    tempLabel.setOpaque(false);
                    tempLabel.setFont(actualRenderer.getFont());
                    cellPanel.add(tempLabel, Utilities.getConstraints(constraints, GridBagConstraints.RELATIVE, GridBagConstraints.RELATIVE, GridBagConstraints.REMAINDER, 1, 1, 0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL));
                    totalString = totalString.substring(totalString.indexOf('\n')+1);
                    rows++;
                }
                tempLabel = new JLabel(totalString );
                tempLabel.setHorizontalAlignment(JLabel.CENTER);
                tempLabel.setFont(actualRenderer.getFont());
                cellPanel.add(tempLabel, Utilities.getConstraints(constraints, GridBagConstraints.RELATIVE, GridBagConstraints.RELATIVE, GridBagConstraints.REMAINDER, GridBagConstraints.REMAINDER, 1, 1, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0,0,3,0)));
               
                headerComponent = cellPanel;
                panel.removeAll();
                panel.add(headerComponent, Utilities.getConstraints(constraints,
                                            GridBagConstraints.RELATIVE,
                                            GridBagConstraints.RELATIVE,
                                            GridBagConstraints.RELATIVE,
                                            GridBagConstraints.REMAINDER,
                                            1,
                                            1,
                                            GridBagConstraints.NORTH,
                                            GridBagConstraints.BOTH,
                                            new Insets(3,3,3,3)));
                int h = (tempLabel.getFontMetrics(tempLabel.getFont()).getHeight() + 10) * rows; //headerComponent.getPreferredSize().height ;
                if (h > maxHeight)
                {
                   maxHeight = h;
                }
            }
            else
            {
                JLabel label = (JLabel) actualRenderer;
                label.setText((value == null) ? "" : value.toString() );
                label.setHorizontalAlignment(JLabel.CENTER);
                label.setVerticalAlignment(JLabel.NORTH);
                label.setOpaque(false);
               
                headerComponent = label;
                panel.removeAll();
                panel.add(headerComponent, Utilities.getConstraints(constraints,
                                            GridBagConstraints.RELATIVE,
                                            GridBagConstraints.RELATIVE,
                                            GridBagConstraints.RELATIVE,
                                            GridBagConstraints.REMAINDER,
                                            1,
                                            1,
                                            GridBagConstraints.NORTH,
                                            GridBagConstraints.NONE,
                                            new Insets(3,3,3,3)));
               
                int h = headerComponent.getPreferredSize().height ;
                if (h > maxHeight)
                {
                   maxHeight = h;
                }
            }
             
             panel.setPreferredSize(new Dimension((int)headerComponent.getPreferredSize().getWidth() + 30,maxHeight + pady));
             
             return panel;
        }
       
    }   
mgs
 
Posts: 48
Joined: Mon Dec 01, 2008 11:01 am

Re: Multiline TableHeader

Postby JIDE Support » Mon Jun 08, 2009 11:48 am

Please try override AutoFilterTableHeader#createDefaultEditor() to customize the editor class, just like you did at the renderer class.

The default implementation of AutoFilterTableHeader#createDefaultEditor() is listed below, FYI.

Code: Select all
    protected TableCellEditor createDefaultEditor() {
        if (isAutoFilterEnabled()) {
            return new AutoFilterTableHeaderEditor() {
                @Override
                protected void customizeAutoFilterBox(AutoFilterBox autoFilterBox) {
                    autoFilterBox.applyComponentOrientation(AutoFilterTableHeader.this.getComponentOrientation());
                    super.customizeAutoFilterBox(autoFilterBox);
                    AutoFilterTableHeader.this.customizeAutoFilterBox(autoFilterBox);
                }
            };
        }
        else {
            return null;
        }
    }


Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: Multiline TableHeader

Postby cpea » Mon Mar 29, 2010 3:59 pm

Here is a solution to get multiline headers working with SortableTable. You can use HTML in your header names to specify how you want it to wrap eg. <html>Multiline<br>Header</html>.

Code: Select all
      myTable = new SortableTable(myModel) {
            protected JTableHeader createDefaultTableHeader() {
                return new MultilineTableHeader(columnModel);
            }
        };


  /**
     * BUG: Default JTable header renderer does not properly calculate
     * preferred height when any of the columns has a multiline column name.
     * This is a fix proposed on the sun website.
     * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4292511
     */   
    private static class MultilineTableHeader extends SortableTableHeader {
        private int preferrredHeight = -1;

        public MultilineTableHeader(TableColumnModel cm) {
            super(cm);
        }

        private Component getHeaderRenderer(int columnIndex) {
            TableColumn aColumn = getColumnModel().getColumn(columnIndex);
            TableCellRenderer renderer = aColumn.getHeaderRenderer();
            if (renderer == null) {
                renderer = getDefaultRenderer();
            }
            return renderer.getTableCellRendererComponent(getTable(), aColumn.getHeaderValue(), false, false, -1, columnIndex);
        }

        private int getPreferredHeight() {
            if (preferrredHeight == -1) {
                preferrredHeight = 0;
                TableColumnModel columnModel = getColumnModel();
                for (int column = 0; column < columnModel.getColumnCount(); column++) {
                    Component comp = getHeaderRenderer(column);
                    int rendererHeight = comp.getPreferredSize().height;
                    preferrredHeight = Math.max(preferrredHeight, rendererHeight);
                }
            }
            return preferrredHeight;
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(super.getPreferredSize().width, getPreferredHeight());
        }

        @Override
        public void columnAdded(TableColumnModelEvent e) {
            preferrredHeight = -1;
            super.columnAdded(e);
        }

        @Override
        public void columnRemoved(TableColumnModelEvent e) {
            preferrredHeight = -1;
            super.columnRemoved(e);
        }
    }
cpea
 
Posts: 1
Joined: Mon Mar 29, 2010 3:55 pm

Re: Multiline TableHeader

Postby JIDE Support » Mon Mar 29, 2010 4:30 pm

Thanks for sharing. We will try to include your code in default SortableTableHeader in 2.9.0.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Re: Multiline TableHeader

Postby JIDE Support » Wed Apr 21, 2010 10:33 am

Just so you know, your code is included in 2.9.0 just released.

Thanks,
JIDE Software Technical Support Team
JIDE Support
Site Admin
 
Posts: 37219
Joined: Sun Sep 14, 2003 10:49 am

Custmizing Header List renderer

Postby brocade123 » Tue Oct 05, 2010 3:09 pm

HI,
My table model returns JLabel for some of the columns (which is used to create SortableTableModel) asa result the AutoFilterbox List which contains all possible values displays
JLabel.toString instaed of the column value in filter List.
I am trying to customize AutoFilterTableHeaderRenderer in following way




TableColumn tableColumn = portColumnModel.getColumn(column);
if(column==7 || column==8 || column==9 ){
tableColumn.setCellRenderer(CustomColumnRenderer.getInstance());
AutoFilterTableHeaderRenderer headerRenderer=new AutoFilterTableHeaderRenderer();
headerRenderer.setListCellRenderer(new CustomListCellRenderer());

tableColumn.setHeaderRenderer(headerRenderer());




private static class CustomListCellRenderer extends DefaultListCellRenderer {


public Component getListCellRendererComponent(JList list, Object value,int index,boolean isSelected, boolean cellHasFocus)

{

super.getListCellRendererComponent(list, value,
index, isSelected, cellHasFocus);
setText((String) value);

return this;

}
}


but the filter Drop down for these columns still displays JLabel.toSTring instead of column values.
Control never goes inside getListCellRendererComponent.

Custom cell renderer works fine and I see values in table column but header still shows JLabel.toString for this columns

Appreciate your help
brocade123
 
Posts: 3
Joined: Tue Sep 28, 2010 4:22 pm

Next

Return to Product Suggestions

Who is online

Users browsing this forum: No registered users and 2 guests