/*

   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

 */
package org.apache.batik.svggen;

import java.awt.Component;
import java.awt.Rectangle;

import javax.swing.AbstractButton;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JMenuBar;
import javax.swing.JPopupMenu;
import javax.swing.JProgressBar;
import javax.swing.JScrollBar;
import javax.swing.JToolBar;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.plaf.ComponentUI;

import org.w3c.dom.Element;

/**
 * This class offers a way to create an SVG document with grouping
 * that reflects the Swing composite structure (container/components).
 *
 * @author Vincent Hardy
 * @version $Id$
 */
public abstract class SwingSVGPrettyPrint implements SVGSyntax {

    /**
     * @param cmp Swing component to be converted to SVG
     * @param svgGen SVGraphics2D to use to paint Swing components
     */
    public static void print(JComponent cmp, SVGGraphics2D svgGen) {
        if ((cmp instanceof JComboBox) || (cmp instanceof JScrollBar)) {
            // This is a work around unresolved issue with JComboBox
            // and JScrollBar
            printHack(cmp, svgGen);
            return;
        }

        // Spawn a new Graphics2D for this component
        SVGGraphics2D g = (SVGGraphics2D)svgGen.create();
        g.setColor(cmp.getForeground());
        g.setFont(cmp.getFont());
        Element topLevelGroup = g.getTopLevelGroup();

        // If there is no area to be painted, return here
        if ((cmp.getWidth() <= 0) || (cmp.getHeight() <= 0))
            return;

        Rectangle clipRect = g.getClipBounds();
        if (clipRect == null)
            g.setClip(0, 0, cmp.getWidth(), cmp.getHeight());

        paintComponent(cmp, g);
        paintBorder(cmp, g);
        paintChildren(cmp, g);

        // Now, structure DOM tree to reflect this component's structure
        Element cmpGroup = g.getTopLevelGroup();
        cmpGroup.setAttributeNS(null, "id",
                                svgGen.getGeneratorContext().idGenerator.
                                generateID(cmp.getClass().getName()));

        topLevelGroup.appendChild(cmpGroup);
        svgGen.setTopLevelGroup(topLevelGroup);
    }

    /**
     * @param cmp Swing component to be converted to SVG
     * @param svgGen SVGraphics2D to use to paint Swing components
     */
    private static void printHack(JComponent cmp, SVGGraphics2D svgGen) {
        // Spawn a new Graphics2D for this component
        SVGGraphics2D g = (SVGGraphics2D)svgGen.create();
        g.setColor(cmp.getForeground());
        g.setFont(cmp.getFont());
        Element topLevelGroup = g.getTopLevelGroup();

        // If there is no area to be painted, return here
        if ((cmp.getWidth() <= 0) || (cmp.getHeight() <= 0))
            return;

        Rectangle clipRect = g.getClipBounds();
        if (clipRect == null) {
            g.setClip(0, 0, cmp.getWidth(), cmp.getHeight());
        }

        cmp.paint(g);

        // Now, structure DOM tree to reflect this component's structure
        Element cmpGroup = g.getTopLevelGroup();
        cmpGroup.setAttributeNS(null, "id",
                                svgGen.getGeneratorContext().idGenerator.
                                generateID(cmp.getClass().getName()));

        topLevelGroup.appendChild(cmpGroup);
        svgGen.setTopLevelGroup(topLevelGroup);
    }


    private static void paintComponent(JComponent cmp, SVGGraphics2D svgGen){
        ComponentUI ui = UIManager.getUI(cmp);
        if(ui != null){
            ui.installUI(cmp);
            ui.update(svgGen, cmp);
        }
    }

    /**
     * WARNING: The following code does some special case processing
     * depending on the class of the input JComponent. This is needed
     * because there is no generic way I could find to determine whether
     * a component should be painted or not.
     */
    private static void paintBorder(JComponent cmp, SVGGraphics2D svgGen){
        Border border = cmp.getBorder();
        if(border != null){
            if( (cmp instanceof AbstractButton)
                ||
                (cmp instanceof JPopupMenu)
                ||
                (cmp instanceof JToolBar)
                ||
                (cmp instanceof JMenuBar)
                ||
                (cmp instanceof JProgressBar) ){
                if( ((cmp instanceof AbstractButton) && ((AbstractButton)cmp).isBorderPainted())
                    ||
                    ((cmp instanceof JPopupMenu) && ((JPopupMenu)cmp).isBorderPainted())
                    ||
                    ((cmp instanceof JToolBar) && ((JToolBar)cmp).isBorderPainted())
                    ||
                    ((cmp instanceof JMenuBar) && ((JMenuBar)cmp).isBorderPainted())
                    ||
                    ((cmp instanceof JProgressBar) && ((JProgressBar)cmp).isBorderPainted() ))
                    border.paintBorder(cmp, svgGen, 0, 0, cmp.getWidth(), cmp.getHeight());
            } else {
                border.paintBorder(cmp, svgGen, 0, 0, cmp.getWidth(), cmp.getHeight());
            }
        }
    }

    private static void paintChildren(JComponent cmp, SVGGraphics2D svgGen){
        int i = cmp.getComponentCount() - 1;
        Rectangle tmpRect = new Rectangle();

        for(; i>=0; i--){
            Component comp = cmp.getComponent(i);

            if( comp != null && JComponent.isLightweightComponent(comp) && comp.isVisible() ) {
                Rectangle cr = null;
                boolean isJComponent = (comp instanceof JComponent);

                if(isJComponent) {
                    cr = tmpRect;
                    ((JComponent)comp).getBounds(cr);
                } else {
                    cr = comp.getBounds();
                }

                boolean hitClip =
                    svgGen.hitClip(cr.x, cr.y, cr.width, cr.height);

                if (hitClip) {
                    SVGGraphics2D cg = (SVGGraphics2D)svgGen.create(cr.x, cr.y, cr.width, cr.height);
                    cg.setColor(comp.getForeground());
                    cg.setFont(comp.getFont());
                    if(comp instanceof JComponent)
                        print((JComponent)comp, cg);
                    else{
                        comp.paint(cg);
                    }
                }
            }
        }
    }
}
