home
products
education
support
partners
company

introduction

get started

articles

manual

tutorials

reference docs

case studies

knowledge base

goodies

screenshots

demos

echoes

Carousel zone


SourceForge.net Logo

home

forums

downloads

bugs

mailing list
XUI Zone - articles

number of ratings 1
average rating 5.00

The Carousel tables which are used in the SugarCRM application are bound to the XModel through the use of some simple declarations. If we start by looking at the screenshot in figure 1 below we can see a table which is populated with data from the cachedaccounts.xml file.

Figure 1 - The table containing a list of accounts stored in the cachedaccounts file

The declaration of the table is made in the offlinemenu.xml file as shown in listing 1.

Listing 1 - The declaration of the table in the offlinemenu page

   

The data we will be binding to is contained in the cachedaccounts.xml file which is loaded when the application starts up. For more on the loading of this file go to the section outlining the use of local routes. Now the cachedaccounts.xml file contains many more attributes than are being displayed in figure 1 and the titles of the column headers have more meaningful text than the attribute names. In order to do this we introduce a mapping file called tabledefs.xml which contains the mapping declaration for the table as shown in listing 2.

Listing 2 - The cachedAccountHeader declaration in the tabledefs file

  
  
  
  
  

The id attribute in each of the nodes refers to the attribute of the account node in the cachedaccounts.xml dataset. The title attribute is the key into the language file for the text which will be displayed in the header for that particular attribute.

Now in order to map this title header to the table we need to use the TableHelper class which is called as shown in listing 3.

Listing 3 - Calling the TableHelper class
  private void setupTable()
  {
    TableHelper helper = new TableHelper();
    helper.setupSpecificTable( accountsTable, "tableheaders/cachedAccountHeader", 
                "retrievedaccounts", getComponentFactory() );
  }

The first parameter is the table itself. The second is the path in the XModel to the table header definition shown in listing 2. The third parameter is the path to the XModel whose data is to be displayed and the final parameter is the component factory which the table will use.

Now we can take a look at the setupSpecificTable method of the TableHelper class as shown in listing 4

Listing 4 - The setupSpecificTable method of the TableHelper class
  public void setupSpecificTable( XBaseTable table, String headerPath, String modelPath
        , XComponentFactory compFact )
  {
    table.setTranslate( false );
    XBaseModel tableMdl = ( XBaseModel )rootModel.get( modelPath );
    XBaseModel attibsMdl = ( XBaseModel )rootModel.get( headerPath );
    SpecificModelAdapter sma = new SpecificModelAdapter( tableMdl );
    sma.setAttributesModel( attibsMdl );
    table.setTableModelAdapter( sma, null );
    setHeaderRenderer( table );
    table.setDefaultRenderer ( String.class, new Table2CellRenderer ( ( XStyleFactory ) 
                compFact, true ) );
    table.setGridColor ( Color.white );
  }

The first line tells the table not to translate it's data. The next two get references to the models specified by the headerPath and modelPath parameters. The next three lines deal with setting up a SpecificModelAdapter for the table which will be explained futher on. The next line sets the attribute model. The setHeaderRenderer method iterates the table headers and sets custom headers for each. Next the renderer for the table is set to the Table2CellRenderer which, again, is dealt with further on.

Now we can look at the SpecificModelAdapter which is used to retrieve data from the model. Listing 5 shows the constructor which takes the data XModel as a parameter and the setAttributesModel method which takes the table header XModel shown in listing 2 as a parameter.

Listing 5 - Constructor and setAttributesModel method of the SpecificModelAdapter
  public SpecificModelAdapter( XModel newModel ) {
    super( newModel );
    listeners = new Vector();
    model = newModel;
  }
  
  public void setAttributesModel( XModel attributeMdl )
  {
    attribMdl = attributeMdl;
  }

Next we can look at the getRowCount and getColumnCount functions shown in listing 6. The getRowCount function uses the getNumChildren function of the XModel to get a count of it's children. And the getColumnCount function uses the same function to get a count of it's children.

Listing 6 - Methods of the SpecificModelAdapter
  public int getRowCount()
  {
   return model.getNumChildren();
  }
  
  public int getColumnCount()
  {
    return attribMdl.getNumChildren();
  }

  public String getColumnName(int columnIndex)
  {
    XModel colMdl = ( XModel )attribMdl.get( columnIndex );
    return XModelHelper.getAttrib( colMdl, "title" );
  }

  public Object getValueAt( int rowIndex, int columnIndex )
  {
    XModel tempMdl = ( XModel ) attribMdl.get( columnIndex );
    XModel rowMdl = ( XModel )model.get( rowIndex );
    return XModelHelper.getAttrib( rowMdl, tempMdl.getId() );
  }

Next the getColumnName function retrieves the header model at the specified index and uses the XModelHelper to return the title attribute. The getValueAt function retrieves the header XModel at columnIndex and the data XModel at the rowIndex. Then the attribute of the row model specified by the name of the header model id is returned. This will return the text which is displayed in the table cells.

The Table2CellRenderer we looked at earlier simply sets up some styles in it's constructor as shown in listing 7.

Listing 7 - The Table2CellRenderer constructor
  public Table2CellRenderer( XStyleFactory styleFactory, boolean useHyper ) 
  {
    styleFact = styleFactory;
    XStyleManager styleMgr = XProjectManager.getStyleManager();
    XProject currentProject = XProjectManager.getCurrentProject();
    translator = currentProject.getTranslator();
    
    dataStyle = styleMgr.getStyle( "table" );
    altDataStyle = styleMgr.getStyle( "alttable" );
    dataStyleSel = styleMgr.getStyle( "table/selected" );
    altDataStyleSel = styleMgr.getStyle( "alttable/selected" );
    hyper = useHyper;
  }     

Then in the getTableCellRendererComponent function shown in listing 8, the row colours are alternated based on the table styles.

Listing 8 - The getTableCellRendererComponent function of the Table2CellRenderer
  public Component getTableCellRendererComponent( JTable table, Object value, 
        boolean isSelected, boolean hasFocus, int row, int column )
  {
    setValue( value );
    Component lbl = null;
    if ( hyper && column == 0  ) {
      lbl = new JLabel( getText() );
    } else {
      lbl = new JLabel( getText() );
    }
    ( ( JLabel ) lbl ).setOpaque( true );
    setOpaque( true );

    if ( isSelected ) 
      styleFact.applyStyle( this, (( row % 2 ) == 0 ) ? dataStyleSel : 
                altDataStyleSel );
    else 
      styleFact.applyStyle( this, (( row % 2 ) == 0 ) ? dataStyle : altDataStyle );
      
    return this;
  }

comments


If you were logged in you could rate this article or add a comment.