/*
 * MMCDTreeView.java
 * 
 * Created on 25 �ubat 2005 Cuma, 10:49
 */

package com.isoft.mmcd.skin.widgets ;

import com.isoft.mmcd.utils.* ;
import com.isoft.mmcd.utils.cfgreader.* ;
import com.isoft.mmcd.skin.* ;
import com.isoft.mmcd.application.handlers.controllers.OptionRefresher ;
import com.isoft.mmcd.exceptions.* ;

import java.awt.* ;
import java.io.Serializable ;
import java.util.ArrayList ;

import javax.imageio.ImageIO ;
import javax.swing.* ;
import javax.swing.tree.* ;

/**
 * 
 * @author Fatih ATAK
 */
public class MMCDTreeView extends JTree implements java.io.Serializable, Widget, ResizableWidget, ScrollableWidget
{
    public static class TreeNode implements Cloneable, Serializable
    {
        protected static final int TYPE_NONE = 0 ;

        protected static final int TYPE_TURKISH = TYPE_NONE ;

        protected static final int TYPE_ARABIC = 2 ;

        public String text = "" ;

        public String displayText = "" ;

        public String fileName = "" ;

        public String firstChildFileName = null ;

        public String nextFileName = "" ;

        public String contentBound = "" ;

        public int docid = 0 ;

        public int type = 0 ;

        public String extra = null ;

        public MCCompoundProperty decleration ;

        public int bookId ;

        public int search_count = 0 ;

        public String original_text = "" ;

        public int myLevel ;

        public boolean searchLeaf = false ;

        public TreeNode( )
        {
            /* nothing to do */
        }

        public Object clone( )
        {
            MMCDTreeView.TreeNode clonedNode = new MMCDTreeView.TreeNode( ) ;
            clonedNode.fileName = this.fileName ;
            clonedNode.nextFileName = this.nextFileName ;
            clonedNode.docid = this.docid ;
            clonedNode.text = this.text ;
            clonedNode.extra = this.extra ;
            clonedNode.bookId = this.bookId ;
            clonedNode.search_count = this.search_count ;
            clonedNode.original_text = this.original_text ;
            clonedNode.firstChildFileName = this.firstChildFileName ;
            clonedNode.contentBound = this.contentBound ;
            clonedNode.myLevel = this.myLevel ;
            clonedNode.searchLeaf = this.searchLeaf ;
            clonedNode.type = this.type ;
            clonedNode.displayText = this.displayText ;

            return clonedNode ;
        }

        public TreeNode( MCCompoundProperty p, boolean isTitleCase )
        {
            decleration = p ;

            /*
             if( p.getAtomicProperty( "$docid" ) != null )
             docid = p.getAtomicProperty( "$docid" ).getNumericValue( ) ;
             else
             docid = 0 ;
             */

            if( p.getAtomicProperty( "$text" ) != null )
                text = p.getAtomicProperty( "$text" ).getValue( ) ;
            else
                text = "-- Bilinmiyor --" ;

            if( isTitleCase )
                text = StringUtils.toTitleCaseTR( text ) ;

            this.original_text = this.text ;

            if( p.getAtomicProperty( "$type" ) != null )
                type = p.getAtomicProperty( "$type" ).getNumericValue( ) ;
            else
                type = StringUtils.isArabic( text ) ? TYPE_ARABIC : TYPE_TURKISH ;

            this.displayText = "<html><body><span style='" + OptionRefresher.getFontString( type == TYPE_ARABIC ? "tree_arabic_font" : "tree_turkish_font", "tree_color" ) + "'>" + text +"</span></body></html>" ;

            if( p.getAtomicProperty( "$file" ) != null )
                fileName = p.getAtomicProperty( "$file" ).getValue( ) ;
            else
                fileName = null ;

            if( p.getAtomicProperty( "$encoding" ) != null )
                nextFileName = p.getAtomicProperty( "$encoding" ).getValue( ) ;
            else
                nextFileName = null ;

            /*
             if( p.getAtomicProperty( "$extra" ) != null )
             {
             extra = "" ;
             for( int i = 0; i < p.getAtomicProperty( "$extra" ).getNumValues( ); ++i )
             extra += p.getAtomicProperty( "$extra" ).getValue( i ) + "|" ;
             }
             else
             extra = null ;
             */

            if( p.getAtomicProperty( "$bookid" ) != null )
                bookId = p.getAtomicProperty( "$bookid" ).getNumericValue( ) ;
            else
                bookId = 0 ;
        }

        public String toString( )
        {
            if( displayText.length( ) == 0 )
                displayText = text ;
            return displayText ;
        }

    }

    protected String helpId = "" ;

    protected String widgetName = "" ;

    protected String popupMenuName = null ;

    protected DynamicWidgetBounds dwbounds = null ;

    protected MMCDScrollPane scrollPane = null ;

    protected boolean isTitleCase = true ;

    protected boolean postProcessTree = false ;

    private ArrayList rowsToExpand = new ArrayList( ) ;

    private ArrayList rowsToSelect = new ArrayList( ) ;

    private int currentRow = 0 ;

    public String getWidgetName( )
    {
        return widgetName ;
    }

    public void setWidgetName( String widgetName )
    {
        this.widgetName = widgetName ;
    }

    /** Creates a new instance of MMCDTreeView */
    public MMCDTreeView( )
    {
        super( ) ;
        setScrollPane( new MMCDScrollPane( this ) ) ;
        getSelectionModel( ).setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION ) ;
        setAutoscrolls( true ) ;
        setScrollsOnExpand( true ) ;
        setLargeModel( true ) ;
        setExpandsSelectedPaths( true ) ;
    }

    public boolean init( MCCompoundProperty property ) throws MMCDException
    {
        try
        {
            // MouseListener ml = new DefaultTreeMouseListener( this ) ;
            // addMouseListener( ml ) ;

//            if( property.getAtomicProperty( "$opaque" ) != null )
//            {
//                if( !property.getAtomicProperty( "$opaque" ).getBooleanValue( ) )
//                {
//                    // if( getCellRenderer( ) instanceof DefaultTreeCellRenderer )
//                    // {
//                    //    ( ( DefaultTreeCellRenderer )getCellRenderer( ) ).setOpaque( false ) ;
//                    //    ( ( DefaultTreeCellRenderer )getCellRenderer( ) ).setBackgroundNonSelectionColor( new Color( 1.0f, 1.0f, 1.0f, 0.0f ) ) ;
//                    // }
//                    getScrollPane( ).getViewport( ).setOpaque( false ) ;
//                    if( getScrollPane( ).getViewport( ).getView( ) instanceof JComponent )
//                        ( ( JComponent )getScrollPane( ).getViewport( ).getView( ) ).setOpaque( false ) ;
//                }
//            }

            if( property.getAtomicProperty( "$multiple" ) != null )
            {
                if( property.getAtomicProperty( "$multiple" ).getBooleanValue( ) )
                    this.getSelectionModel( ).setSelectionMode( TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION ) ;
            }

            if( property.getAtomicProperty( "$titlecase" ) != null )
            {
                this.isTitleCase = property.getAtomicProperty( "$titlecase" ).getBooleanValue( ) ;
            }

            if( property.getAtomicProperty( "$postprocess" ) != null )
            {
                this.postProcessTree = property.getAtomicProperty( "$postprocess" ).getBooleanValue( ) ;
            }

            if( property.getCompoundProperty( "@cellrenderer" ) != null )
            {
                MCCompoundProperty crcp = property.getCompoundProperty( "@cellrenderer" ) ;

                DefaultTreeCellRenderer cr = ( DefaultTreeCellRenderer )this.getCellRenderer( ) ;

                MCProperty p ;

                if( ( p = crcp.getAtomicProperty( "$bgcolor" ) ) != null )
                    cr.setBackground( p.getColorValue( ) ) ;

                if( ( p = crcp.getAtomicProperty( "$itembgcolor" ) ) != null )
                    cr.setBackgroundNonSelectionColor( p.getColorValue( ) ) ;

                if( ( p = crcp.getAtomicProperty( "$selectedbgcolor" ) ) != null )
                    cr.setBackgroundSelectionColor( p.getColorValue( ) ) ;

                if( ( p = crcp.getAtomicProperty( "$selectedbordercolor" ) ) != null )
                    cr.setBorderSelectionColor( p.getColorValue( ) ) ;

                if( ( p = crcp.getAtomicProperty( "$textcolor" ) ) != null )
                    cr.setTextNonSelectionColor( p.getColorValue( ) ) ;

                if( ( p = crcp.getAtomicProperty( "$textselectioncolor" ) ) != null )
                    cr.setTextSelectionColor( p.getColorValue( ) ) ;

                if( ( p = crcp.getAtomicProperty( "$font" ) ) != null )
                    cr.setFont( p.getFontValue( ) ) ;

                if( ( p = crcp.getAtomicProperty( "$closedicon" ) ) != null )
                    cr.setClosedIcon( new ImageIcon( ImageIO.read( p.getInputWrapper( ).getStream( ) ) ) ) ;

                if( ( p = crcp.getAtomicProperty( "$leaficon" ) ) != null )
                    cr.setLeafIcon( new ImageIcon( ImageIO.read( p.getInputWrapper( ).getStream( ) ) ) ) ;

                if( ( p = crcp.getAtomicProperty( "$openicon" ) ) != null )
                    cr.setOpenIcon( new ImageIcon( ImageIO.read( p.getInputWrapper( ).getStream( ) ) ) ) ;

                if( ( p = crcp.getAtomicProperty( "$opaque" ) ) != null )
                {
                    ( ( DefaultTreeCellRenderer )getCellRenderer( ) ).setOpaque( p.getBooleanValue( ) ) ;
                    if( ( crcp.getAtomicProperty( "$itembgcolor" ) ) == null )
                        cr.setBackgroundNonSelectionColor( new Color( 1.0f, 1.0f, 1.0f, 0.0f ) ) ;
                }
            }

            InputWrapper iw = property.getAtomicProperty( "$treedata" ).getInputWrapper( ) ;

            if( iw != null )
            {
                MCCompoundProperty cprop = PropertyUtils.loadCompoundProperties( iw )[ 0 ] ;

                buildTree( cprop ) ;
            }

            return true ;
        }
        catch( Exception e )
        {
            System.err.println( "Error while initializing TreeView" ) ;
            e.printStackTrace( ) ;
            throw new MMCDException( e ) ;
        }
    }

    public void buildTree( MCCompoundProperty root )
    {
        String text = ( root.getAtomicProperty( "$text" ) ).getValue( ) ;

        if( isTitleCase )
            text = StringUtils.toTitleCaseTR( text ) ;

        MMCDTreeView.TreeNode rootUserNode = new MMCDTreeView.TreeNode( ) ;
        rootUserNode.text = text ;

        rootUserNode.type = StringUtils.isArabic( text ) ? TreeNode.TYPE_ARABIC : TreeNode.TYPE_TURKISH ;

        rootUserNode.displayText = "<html><body><span style='" + OptionRefresher.getFontString( rootUserNode.type == TreeNode.TYPE_ARABIC ? "tree_arabic_font" : "tree_turkish_font", "tree_color" ) + "'>" + rootUserNode.text +"</span></body></html>" ;

        DefaultMutableTreeNode dmtnode = new DefaultMutableTreeNode( rootUserNode ) ;

        buildTreeFromProperty( root, dmtnode ) ;

        DefaultTreeModel mdl = new DefaultTreeModel( dmtnode ) ;
        setModel( mdl ) ;

        System.out.println( "Expanding rows:" + this.rowsToExpand.size( ) ) ;

        for( int i = 0; i < this.rowsToExpand.size( ); ++i )
        {
            DefaultMutableTreeNode node = ( DefaultMutableTreeNode )this.rowsToExpand.get( i ) ;
            if( node.isLeaf( ) )
                node = ( DefaultMutableTreeNode )node.getParent( ) ;
            TreePath pathToExpand = new TreePath( node.getPath( ) ) ;
            System.out.println( "row " + i + ":" + pathToExpand.toString( ) ) ;
            this.expandPath( pathToExpand ) ;
        }

        System.out.println( "Selecting rows:" + this.rowsToSelect.size( ) ) ;

        for( int i = 0; i < this.rowsToSelect.size( ); ++i )
        {
            DefaultMutableTreeNode node = ( DefaultMutableTreeNode )this.rowsToSelect.get( i ) ;
            //if( node.isLeaf( ) )
            // node = ( DefaultMutableTreeNode )node.getParent( ) ;
            TreePath pathToSelect = new TreePath( node.getPath( ) ) ;
            System.out.println( "row " + i + ":" + pathToSelect.toString( ) ) ;
            this.addSelectionPath( pathToSelect ) ;
        }
        this.rowsToExpand = new ArrayList( ) ;

        if( this.postProcessTree )
            postProcessTree( dmtnode ) ;
    }

    public void postProcessTree( DefaultMutableTreeNode root )
    {
        //System.out.println( "level :" + root.getLevel( ) ) ;

        TreeNode node = null ;
        node = ( TreeNode )root.getUserObject( ) ;
        if( !root.isLeaf( ) )
        {
            TreeNode node2 = null ;

            DefaultMutableTreeNode tnode = ( DefaultMutableTreeNode )root.getChildAt( 0 ) ;
            node2 = ( TreeNode )tnode.getUserObject( ) ;

            node.firstChildFileName = node2.fileName ;
            node.contentBound = node.firstChildFileName ;

            for( int i = 0; i < root.getChildCount( ); ++i )
                postProcessTree( ( DefaultMutableTreeNode )root.getChildAt( i ) ) ;
        }
        else
        {
            node.firstChildFileName = null ;
            node.contentBound = node.nextFileName ;
        }

        node.myLevel = root.getLevel( ) ;

        //TODO uncoment below -- mustafa bu hala lazım mı? değilse silelim
        /*
         if( root.getLevel( ) == 2 )
         {
         DefaultMutableTreeNode girisNode = new DefaultMutableTreeNode( ) ;
         
         MMCDTreeView.TreeNode girisUserNode = new MMCDTreeView.TreeNode( ) ;
         girisUserNode = ( MMCDTreeView.TreeNode )( ( MMCDTreeView.TreeNode )root.getUserObject( ) ).clone( ) ;
         girisUserNode.text = "Giriş.." ;
         
         girisUserNode.fileName = girisUserNode.fileName.replaceAll("do0","do1"); 
         girisUserNode.fileName = girisUserNode.fileName.replaceAll("en-0","en-1");
         
         girisUserNode.nextFileName = girisUserNode.firstChildFileName ;
         
         girisUserNode.firstChildFileName = null;
         girisUserNode.contentBound = girisUserNode.nextFileName; 
         girisUserNode.myLevel = 3;
         
         girisNode.setUserObject( girisUserNode ) ;
         root.insert( girisNode, 0 ) ;
         }*/

    }

    public void rebuildTree( DefaultMutableTreeNode root )
    {

        TreeNode node = null ;
        node = ( TreeNode )root.getUserObject( ) ;
        if( !root.isLeaf( ) )
        {
            TreeNode node2 = null ;

            DefaultMutableTreeNode tnode = ( DefaultMutableTreeNode )root.getChildAt( 0 ) ;
            node2 = ( TreeNode )tnode.getUserObject( ) ;

            node.firstChildFileName = node2.fileName ;
            node.contentBound = node.firstChildFileName ;

            for( int i = 0; i < root.getChildCount( ); ++i )
                postProcessTree( ( DefaultMutableTreeNode )root.getChildAt( i ) ) ;
        }
        else
        {
            node.firstChildFileName = null ;
            node.contentBound = node.nextFileName ;
        }

        node.myLevel = root.getLevel( ) ;

        if( root.getLevel( ) == 2 )
        {
            DefaultMutableTreeNode girisNode = new DefaultMutableTreeNode( ) ;

            MMCDTreeView.TreeNode girisUserNode = new MMCDTreeView.TreeNode( ) ;
            girisUserNode = ( MMCDTreeView.TreeNode )( ( MMCDTreeView.TreeNode )root.getUserObject( ) ).clone( ) ;
            girisUserNode.text = "Giriş.." ;

            girisUserNode.fileName = girisUserNode.fileName.replaceAll( "do0", "do1" ) ;
            girisUserNode.fileName = girisUserNode.fileName.replaceAll( "en-0", "en-1" ) ;

            girisUserNode.nextFileName = girisUserNode.firstChildFileName ;

            girisUserNode.firstChildFileName = null ;
            girisUserNode.contentBound = girisUserNode.nextFileName ;
            girisUserNode.myLevel = 3 ;

            girisNode.setUserObject( girisUserNode ) ;
            root.insert( girisNode, 0 ) ;
            // System.out.println( "ekledi" ) ;
        }

    }

    //    public void postProcessTree( DefaultMutableTreeNode root )
    //    {
    //        System.out.println("Depth :"+root.getDepth() );
    //        if(  root.getDepth() == 3 )
    //        {
    //            DefaultMutableTreeNode girisNode = new DefaultMutableTreeNode();
    //            MMCDTreeView.TreeNode girisUserNode = new MMCDTreeView.TreeNode();
    //            girisUserNode.text = "mustafagiris";
    //            girisNode.setUserObject(girisUserNode);
    //            root.add(girisNode);
    //            System.out.println("ekledi" );
    //        }
    //        
    //        if( root.getUserObject( ) instanceof MMCDTreeView.TreeNode )
    //        {
    //            TreeNode node = null ;
    //            node = ( TreeNode )root.getUserObject( ) ;
    //            if( !root.isLeaf( ) )
    //            {
    //                TreeNode node2 = null ;
    //
    //                DefaultMutableTreeNode tnode = ( DefaultMutableTreeNode )root.getChildAt( 0 ) ;
    //                node2 = ( TreeNode )tnode.getUserObject( ) ;
    //
    //                node.firstChildFileName = node2.fileName ;
    //
    //                for( int i = 0; i < root.getChildCount( ); ++i )
    //                    postProcessTree( ( DefaultMutableTreeNode )root.getChildAt( i ) ) ;
    //            }
    //            else
    //            {
    //                node.firstChildFileName = null ;
    //            }
    //        }
    //        else
    //        {
    //            if( !root.isLeaf( ) )
    //            {
    //                for( int i = 0; i < root.getChildCount( ); ++i )
    //                    postProcessTree( ( DefaultMutableTreeNode )root.getChildAt( i ) ) ;
    //            }
    //        }
    //    }

    public int[ ] getPathIndices( DefaultMutableTreeNode node )
    {
        javax.swing.tree.TreeNode[] nodes = node.getPath( ) ;
        int[ ] path = new int[ nodes.length - 1 ] ;

        // until length -1, since we do not have any children for last one
        for( int i = 0; i < nodes.length - 1; ++i )
            path[ i ] = nodes[ i ].getIndex( nodes[ i + 1 ] ) ;

        return path ;
    }

    public int[ ] getPathIndices( )
    {
        DefaultMutableTreeNode node = ( DefaultMutableTreeNode )this.getSelectionPath( ).getLastPathComponent( ) ;
        javax.swing.tree.TreeNode[] nodes = node.getPath( ) ;
        int[ ] path = new int[ nodes.length - 1 ] ;

        // until length -1, since we do not have any children for last one
        for( int i = 0; i < nodes.length - 1; ++i )
            path[ i ] = nodes[ i ].getIndex( nodes[ i + 1 ] ) ;

        return path ;
    }

    public void setSelection( int[ ] selindices )
    {
        DefaultMutableTreeNode node = ( DefaultMutableTreeNode )getModel( ).getRoot( ) ;
        for( int i = 0; i < selindices.length; ++i )
            node = ( DefaultMutableTreeNode )node.getChildAt( selindices[ i ] ) ;
        this.setSelectionPath( new TreePath( node.getPath( ) ) ) ;
    }

    public int[ ][ ] getMultiPathIndices( )
    {
        TreePath[ ] selection = this.getSelectionPaths( ) ;
        int[ ][ ] res = new int[ selection.length ][ 0 ] ;

        for( int i = 0; i < selection.length; ++i )
        {
            DefaultMutableTreeNode node = ( DefaultMutableTreeNode )selection[ i ].getLastPathComponent( ) ;
            javax.swing.tree.TreeNode[] nodes = node.getPath( ) ;
            int[ ] path = new int[ nodes.length - 1 ] ;

            // until length -1, since we do not have any children for last one
            for( int j = 0; j < nodes.length - 1; ++j )
                path[ j ] = nodes[ j ].getIndex( nodes[ j + 1 ] ) ;

            res[ i ] = path ;
        }
        return res ;
    }

    public void setSelections( int[ ][ ] selindices )
    {
        TreePath[ ] sel = new TreePath[ selindices.length ] ;
        for( int j = 0; j < selindices.length; ++j )
        {
            DefaultMutableTreeNode node = ( DefaultMutableTreeNode )getModel( ).getRoot( ) ;
            for( int i = 0; i < selindices[ j ].length; ++i )
                node = ( DefaultMutableTreeNode )node.getChildAt( selindices[ j ][ i ] ) ;
            sel[ j ] = new TreePath( node.getPath( ) ) ;
        }
        this.setSelectionPaths( sel ) ;
    }

    public void changeDataSource( DefaultMutableTreeNode tn )
    {
        setModel( new DefaultTreeModel( tn ) ) ;

    }

    protected int buildTreeFromProperty( MCCompoundProperty prop, DefaultMutableTreeNode root )
    {
        MCCompoundProperty cp = null ;
        int cnt = 0 ;

        while( true )
        {
            cp = prop.getCompoundProperty( "@node" + ( ++cnt ) ) ;
            ++currentRow ;
            if( cp == null )
                break ;
            TreeNode mynode = new MMCDTreeView.TreeNode( cp, this.isTitleCase ) ;
            DefaultMutableTreeNode node = new DefaultMutableTreeNode( mynode ) ;
            buildTreeFromProperty( cp, node ) ;
            root.add( node ) ;
            if( cp.getAtomicProperty( "$isexpand" ) != null && cp.getAtomicProperty( "$isexpand" ).getBooleanValue( ) )
            {
                System.out.println( "property " + cp.getName( ) + " : " + this.currentRow ) ;
                this.rowsToExpand.add( node ) ;
            }
            if( cp.getAtomicProperty( "$isselect" ) != null && cp.getAtomicProperty( "$isselect" ).getBooleanValue( ) )
            {
                System.out.println( "select property " + cp.getName( ) + " : " + this.currentRow ) ;
                this.rowsToSelect.add( node ) ;
            }
        }
        return cnt ;
    }

    public DynamicWidgetBounds getDynamicWidgetBounds( )
    {
        if( getScrollPane( ) != null )
            return getScrollPane( ).getDynamicWidgetBounds( ) ;

        return dwbounds ;
    }

    public void setDynamicWidgetBounds( DynamicWidgetBounds dwb )
    {
        if( getScrollPane( ) != null )
        {
            getScrollPane( ).setDynamicWidgetBounds( dwb ) ;
        }
        else
        {
            this.dwbounds = dwb ;
        }
    }

    public void resizeWidget( Rectangle newParentBounds )
    {
        if( getScrollPane( ) != null )
        {
            getScrollPane( ).resizeWidget( newParentBounds ) ;
        }
        else
        {
            getDynamicWidgetBounds( ).calculateBounds( newParentBounds ) ;
            setBounds( getDynamicWidgetBounds( ).getBounds( ) ) ;
            setPreferredSize( new Dimension( getDynamicWidgetBounds( ).getBounds( ).width, getDynamicWidgetBounds( ).getBounds( ).height ) ) ;
        }
    }

    public MMCDScrollPane getScrollPane( )
    {
        return scrollPane ;
    }

    public void setScrollPane( MMCDScrollPane scrollPane )
    {
        this.scrollPane = scrollPane ;
    }

    public void setVisible( boolean visible )
    {
        super.setVisible( visible ) ;
        if( getScrollPane( ) != null )
            getScrollPane( ).setVisible( visible ) ;
    }

    public void setInheritsPopupMenu( boolean flag )
    {
        super.setInheritsPopupMenu( flag ) ;
        if( getScrollPane( ) != null )
            getScrollPane( ).setInheritsPopupMenu( flag ) ;
    }

    public void setComponentPopupMenu( JPopupMenu popup )
    {
        super.setComponentPopupMenu( popup ) ;
        if( getScrollPane( ) != null )
            getScrollPane( ).setComponentPopupMenu( popup ) ;
    }

    /* (non-Javadoc)
     * @see com.isoft.mmcd.skin.Widget#getPopUpMenuName()
     */
    public String getPopUpMenuName( )
    {
        return this.popupMenuName ;
    }

    /* (non-Javadoc)
     * @see com.isoft.mmcd.skin.Widget#setPopUpMenuName(java.lang.String)
     */
    public void setPopUpMenuName( String popupMenuName )
    {
        this.popupMenuName = popupMenuName ;
    }

    /* (non-Javadoc)
     * @see com.isoft.mmcd.skin.Widget#setHelpId(java.lang.String)
     */
    public void setHelpId( String helpId )
    {
        this.helpId = helpId ;
    }

    /* (non-Javadoc)
     * @see com.isoft.mmcd.skin.Widget#getHelpId()
     */
    public String getHelpId( )
    {
        return this.helpId ;
    }

}