package fr.lteconsulting.hexa.client.ui.htreetable; import java.util.ArrayList; import com.google.gwt.dom.client.Element; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.Widget; public class HTreeTableHeader extends ComplexPanel implements ClickHandler { ItemImpl m_rootItem = new ItemImpl( null ); Element m_thead; ArrayList<Element> m_rows = new ArrayList<Element>(); ArrayList<RowHdrImpl> m_rowHeaders = new ArrayList<RowHdrImpl>(); public HTreeTableHeader() { m_thead = DOM.createTHead(); setElement( m_thead ); addDomHandler( this, ClickEvent.getType() ); } @Override public void onClick( ClickEvent event ) { event.stopPropagation(); event.preventDefault(); } // means to update the col spans... public void draw() { m_rootItem.updateColSpans(); String nbRows = String.valueOf( m_rows.size() ); int nbHeaders = m_rowHeaders.size(); for( int i = 0; i < nbHeaders; i++ ) m_rowHeaders.get( i ).m_td.setAttribute( "rowspan", nbRows ); } public class RowHdrImpl { Element m_tr; Element m_td; public void setText( String text ) { m_td.setInnerText( text ); } } public RowHdrImpl addRowHeader() { RowHdrImpl item = new RowHdrImpl(); m_rowHeaders.add( item ); if( m_rows.isEmpty() ) { Element tr = DOM.createTR(); m_rows.add( tr ); m_thead.appendChild( tr ); } item.m_tr = m_rows.get( 0 ); item.m_td = DOM.createTH(); item.m_tr.appendChild( item.m_td ); return item; } public class ItemImpl { int m_level = -2; int m_nbLeaves = -1; ItemImpl m_parent; ArrayList<ItemImpl> m_childs = new ArrayList<ItemImpl>(); Element m_tr = null; Element m_td = null; ItemImpl( ItemImpl parent ) { m_parent = parent; if( m_parent != null ) m_parent.m_childs.add( this ); } public void setText( String text ) { m_td.setInnerText( text ); } public void setWidget( Widget w ) { setText( "" ); add( w, m_td ); } void updateColSpans() { for( ItemImpl c : m_childs ) { int nbLeaf = c.getNbLeaves(); c.m_td.setAttribute( "colspan", String.valueOf( nbLeaf ) ); c.updateColSpans(); } } int getNbLeaves() { if( m_nbLeaves == -1 ) { if( m_childs.isEmpty() ) m_nbLeaves = 1; else { int nb = 0; for( ItemImpl c : m_childs ) nb += c.getNbLeaves(); m_nbLeaves = nb; } } return m_nbLeaves; } int getLevel() { if( m_level == -2 ) { if( m_parent == null ) m_level = -1; else m_level = 1 + m_parent.getLevel(); } return m_level; } ItemImpl getPreviousAtSameLevel() { return getPreviousAtLevel( getLevel() ); } ItemImpl getLastDescendant( int level ) { int myLevel = getLevel(); if( level > myLevel ) return null; if( myLevel == level ) return this; int i = m_childs.size() - 1; while( i >= 0 ) { ItemImpl t = getLastDescendant( level ); if( t != null ) return t; i--; } return null; } ItemImpl getPreviousAtLevel( int level ) { if( m_parent == null ) return null; ItemImpl position = this; ItemImpl ancestor = m_parent; while( ancestor != null ) { int prevIdx = ancestor.m_childs.indexOf( position ) - 1; while( prevIdx >= 0 ) { // test getLastDescendant( level ) ItemImpl t = ancestor.m_childs.get( prevIdx ).getLastDescendant( level ); if( t != null ) return t; prevIdx--; } // did not find, so go to superior parent position = ancestor; ancestor = ancestor.m_parent; } // did not find, so return null return null; } } public ItemImpl addItem( ItemImpl parentItem ) { ItemImpl item = new ItemImpl( parentItem == null ? m_rootItem : parentItem ); int level = item.getLevel(); while( m_rows.size() < level + 1 ) { Element tr = DOM.createTR(); m_thead.appendChild( tr ); m_rows.add( tr ); } item.m_tr = m_rows.get( level ); // th is inserted after the last child of our parent item.m_td = DOM.createTH(); ItemImpl previousItem = item.getPreviousAtSameLevel(); if( previousItem != null ) item.m_tr.insertAfter( item.m_td, previousItem.m_td ); else item.m_tr.appendChild( item.m_td ); return item; } }