/*
 * WidgetInitializer.java
 *
 * Created on 22 Mayıs 2005 Pazar, 21:15
 */

package com.isoft.mmcd.skin ;

import com.isoft.mmcd.utils.* ;

import com.isoft.mmcd.skin.widgets.* ;
import com.isoft.mmcd.utils.cfgreader.* ;
import com.isoft.mmcd.exceptions.* ;

import java.awt.* ;

import javax.swing.* ;
import javax.swing.border.* ;
import java.lang.reflect.* ;
import javax.imageio.* ;

/**
 *
 * @author Fatih
 */
public class WidgetInitializer implements java.io.Serializable
{

    /** Creates a new instance of WidgetInitializer */
    public WidgetInitializer( )
    {
        /* nothing to do */
    }

    public static void initializeJComponent( MCCompoundProperty cp, JComponent comp ) throws Exception
    {
        /** Optimization Note: Bir tane local MCProperty tanımlayıp iki defa get atomic property yapmak yerine direk ona assign edip sonra kullanırsak
         bir tane get cost undan kurtuluruz.. **/
        MMCDScrollPane scroll = null ;
        JComponent component = comp ;

        if( component instanceof ScrollableWidget )
            scroll = ( ( ScrollableWidget )component ).getScrollPane( ) ;

        if( scroll != null )
            component = scroll ;

        if( ( cp.getCompoundProperty( "@position" ) != null ) && !( component instanceof ResizableWidget ) )
        {
            Rectangle r = cp.getCompoundProperty( "@position" ).getRectangle( ) ;
            component.setBounds( r ) ;
            component.setPreferredSize( new Dimension( r.width, r.height ) ) ;
        }

        if( scroll != null )
            component = comp ;

        if( cp.getAtomicProperty( "$tooltip" ) != null )
            component.setToolTipText( cp.getAtomicProperty( "$tooltip" ).getValue( ) ) ;

        if( cp.getAtomicProperty( "$visible" ) != null )
        {
            component.setVisible( cp.getAtomicProperty( "$visible" ).getBooleanValue( ) ) ;
            if( scroll != null )
                scroll.setVisible( cp.getAtomicProperty( "$visible" ).getBooleanValue( ) ) ;
        }

        if( cp.getAtomicProperty( "$focusable" ) != null )
            component.setFocusable( cp.getAtomicProperty( "$focusable" ).getBooleanValue( ) ) ;

        if( cp.getAtomicProperty( "$opaque" ) != null )
        {
            boolean opaq = cp.getAtomicProperty( "$opaque" ).getBooleanValue( ) ;
            component.setOpaque( opaq ) ;
            if( scroll != null )
            {
                scroll.getViewport( ).setOpaque( opaq ) ;
                if( scroll.getViewport( ).getView( ) instanceof JComponent )
                    ( ( JComponent )scroll.getViewport( ).getView( ) ).setOpaque( opaq ) ;
            }
        }

        if( cp.getAtomicProperty( "$righttoleft" ) != null && cp.getAtomicProperty( "$righttoleft" ).getBooleanValue( ) )
            component.setComponentOrientation( ComponentOrientation.RIGHT_TO_LEFT ) ;

        component.setEnabled( !( cp.getAtomicProperty( "$disabled" ) != null && cp.getAtomicProperty( "$disabled" ).getBooleanValue( ) ) ) ;

        Font font = null ;
        if( cp.getAtomicProperty( "$font" ) != null )
            font = cp.getAtomicProperty( "$font" ).getFontValue( ) ;
        else
            font = Font.decode( null ) ; // get default font

        component.setFont( font ) ;

        if( cp.getAtomicProperty( "$useparentpopup" ) != null )
            component.setInheritsPopupMenu( cp.getAtomicProperty( "$useparentpopup" ).getBooleanValue( ) ) ;

        Method method = null ;

        if( cp.getAtomicProperty( "$text" ) != null )
        {
            try
            {
                method = component.getClass( ).getMethod( "setText", new Class[ ] { "".getClass( ) } ) ;
            }
            catch( Exception ignore )
            {
                // we do not have that method
                method = null ;
            }

            if( method != null )
                method.invoke( component, new Object[ ] { cp.getAtomicProperty( "$text" ).getValue( ) } ) ;
        }

        if( cp.getAtomicProperty( "$margin" ) != null )
        {
            Rectangle tmpr = cp.getAtomicProperty( "$margin" ).getRectangle( ) ;
            Insets ins = new Insets( tmpr.x, tmpr.y, tmpr.width, tmpr.height ) ;

            try
            {
                method = component.getClass( ).getMethod( "setMargin", new Class[ ] { ins.getClass( ) } ) ;
            }
            catch( Exception ignore )
            {
                // we do not have that method
                method = null ;
            }

            if( method != null )
                method.invoke( component, new Object[ ] { ins } ) ;
        }

        if( cp.getAtomicProperty( "$minimumsize" ) != null )
        {
            component.setMinimumSize( cp.getAtomicProperty( "$minimumsize" ).getDimension( ) ) ;
        }

        if( cp.getAtomicProperty( "$color" ) != null )
            component.setForeground( cp.getAtomicProperty( "$color" ).getColorValue( ) ) ;

        if( cp.getAtomicProperty( "$bgcolor" ) != null )
        {
            Color bgc = cp.getAtomicProperty( "$bgcolor" ).getColorValue( ) ;
            component.setBackground( bgc ) ;
            if( scroll != null )
            {
                scroll.getViewport( ).setBackground( bgc ) ;
                if( scroll.getViewport( ).getView( ) instanceof JComponent )
                    ( ( JComponent )scroll.getViewport( ).getView( ) ).setBackground( bgc ) ;
            }
        }

        if( scroll != null )
            component = scroll ;

        if( cp.getAtomicProperty( "$bgpicture" ) != null )
        {
            MCProperty p = cp.getAtomicProperty( "$bgpicture" ) ;
            InputWrapper iw = p.getInputWrapper( ) ;
            ImageIcon ic = new ImageIcon( ImageIO.read( iw.getStream( ) ) ) ;
            iw.getStream( ).close( ) ;
            component.setBorder( new MatteBorder( ic ) ) ;
            component.putClientProperty( "bgpictureproperty", p ) ;
        }
        else if( cp.getAtomicProperty( "$clippedpicture" ) != null )
        {
            MCProperty p = cp.getAtomicProperty( "$clippedpicture" ) ;
            InputWrapper iw = p.getInputWrapper( ) ;
            ImageIcon ic = new ImageIcon( ImageIO.read( iw.getStream( ) ) ) ;
            iw.getStream( ).close( ) ;
            component.setBorder( new MatteBorder( ic ) ) ;
            component.putClientProperty( "clippedpictureproperty", p ) ;
        }
        else if( cp.getAtomicProperty( "$border" ) != null )
        {
            String borderType = cp.getAtomicProperty( "$border" ).getValue( 0 ) ;
            String param1 = cp.getAtomicProperty( "$border" ).getValue( 1 ) ;
            String borderText = ( cp.getAtomicProperty( "$bordertext" ) == null ) ? "" : cp.getAtomicProperty( "$bordertext" ).getValue( ) ;
            if( "bevel".equals( borderType ) )
            {
                if( "raised".equals( param1 ) )
                    component.setBorder( new TitledBorder( new BevelBorder( BevelBorder.RAISED ), borderText, TitledBorder.LEFT, TitledBorder.TOP ) ) ;
                else
                    component.setBorder( new TitledBorder( new BevelBorder( BevelBorder.LOWERED ), borderText, TitledBorder.LEFT, TitledBorder.TOP ) ) ;
            }
            else if( "etched".equals( borderType ) )
            {
                if( "raised".equals( param1 ) )
                    component.setBorder( new TitledBorder( new EtchedBorder( EtchedBorder.RAISED ), borderText, TitledBorder.LEFT, TitledBorder.TOP ) ) ;
                else
                    component.setBorder( new TitledBorder( new EtchedBorder( EtchedBorder.LOWERED ), borderText, TitledBorder.LEFT, TitledBorder.TOP ) ) ;
            }
            else if( "softbevel".equals( borderType ) )
            {
                if( "raised".equals( param1 ) )
                    component.setBorder( new TitledBorder( new SoftBevelBorder( BevelBorder.RAISED ), borderText, TitledBorder.LEFT, TitledBorder.TOP ) ) ;
                else
                    component.setBorder( new TitledBorder( new SoftBevelBorder( BevelBorder.LOWERED ), borderText, TitledBorder.LEFT, TitledBorder.TOP ) ) ;
            }
            else if( "line".equals( borderType ) )
            {
                if( "black".equals( param1 ) )
                    component.setBorder( new TitledBorder( LineBorder.createBlackLineBorder( ), borderText, TitledBorder.LEFT, TitledBorder.TOP ) ) ;
                else
                    component.setBorder( new TitledBorder( LineBorder.createGrayLineBorder( ), borderText, TitledBorder.LEFT, TitledBorder.TOP ) ) ;
            }
            else if( "none".equals( borderType ) )
            {
                component.setBorder( BorderFactory.createEmptyBorder( ) ) ;
            }
            else if( "null".equals( borderType ) )
            {
                component.setBorder( null ) ;
            }
            else
                component.setBorder( new TitledBorder( new SoftBevelBorder( EtchedBorder.RAISED ), borderText, TitledBorder.LEFT, TitledBorder.TOP ) ) ;
            if( font != null )
            {
                if( component.getBorder( ) instanceof TitledBorder )
                    ( ( TitledBorder )component.getBorder( ) ).setTitleFont( font ) ;
            }
        }
        if( scroll != null )
            component = comp ;
    }

    // use pool with care since it is not completely initialized yet
    public static Widget getWidget( MCCompoundProperty cp, WidgetPool pool ) throws MMCDException
    {
        try
        {
            Widget widget = null ;
            JComponent component = null ;
            ResizableWidget rwidget = null ;
            MMCDScrollPane scroll = null ;

            widget = ( Widget )cp.getAtomicProperty( "$class" ).getCustomClassInstance( ) ;

            if( widget instanceof JComponent )
                component = ( JComponent )widget ;
            if( widget instanceof ResizableWidget )
                rwidget = ( ResizableWidget )widget ;
            if( component instanceof ScrollableWidget )
                scroll = ( ( ScrollableWidget )widget ).getScrollPane( ) ;

            if( component != null )
                initializeJComponent( cp, component ) ;

            if( cp.getAtomicProperty( "$popup" ) != null )
                widget.setPopUpMenuName( cp.getAtomicProperty( "$popup" ).getValue( ) ) ;

            // if widget wants to override some settings in above method
            if( widget instanceof WidgetPoolUser )
                ( ( WidgetPoolUser )widget ).init( cp, pool ) ;

            widget.init( cp ) ;

            if( scroll != null )
                scroll.init( cp ) ;

            ResizableWidget tmprwidget = rwidget ;
            if( scroll != null )
                tmprwidget = scroll ;

            if( cp.getAtomicProperty( "$layout" ) == null && widget instanceof Container )
                ( ( Container )widget ).setLayout( null ) ;
            else
            {
                // code to handle layouts
            }

            if( rwidget != null && cp.getCompoundProperty( "@rationalpos" ) != null )
            {
                MCCompoundProperty ctmp = cp.getCompoundProperty( "@rationalpos" ) ;
                tmprwidget.setDynamicWidgetBounds( new DynamicWidgetBounds( ) ) ;
                tmprwidget.getDynamicWidgetBounds( ).setX( ctmp.getAtomicProperty( "$x" ).getDecimalValue( ) ) ;
                tmprwidget.getDynamicWidgetBounds( ).setY( ctmp.getAtomicProperty( "$y" ).getDecimalValue( ) ) ;
                tmprwidget.getDynamicWidgetBounds( ).setWdt( ctmp.getAtomicProperty( "$wdt" ).getDecimalValue( ) ) ;
                tmprwidget.getDynamicWidgetBounds( ).setHgt( ctmp.getAtomicProperty( "$hgt" ).getDecimalValue( ) ) ;
            }

            if( rwidget != null && cp.getCompoundProperty( "@position" ) != null )
                tmprwidget.getDynamicWidgetBounds( ).setAbsoluteRect( cp.getCompoundProperty( "@position" ).getRectangle( ) ) ;

            return widget ;
        }
        catch( Exception e )
        {
            System.err.println( "Exception while initializing widget:(" + cp.getName( ) + ")" ) ;
            e.printStackTrace( ) ;
            throw new MMCDException( e ) ;
        }
    }
}