/*

   Copyright 2001,2003  The Apache Software Foundation 

   Licensed 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.apps.svgbrowser;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.text.AttributedCharacterIterator;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;

import org.apache.batik.gvt.GVTTreeWalker;
import org.apache.batik.gvt.GraphicsNode;
import org.apache.batik.gvt.TextNode;
import org.apache.batik.gvt.text.Mark;
import org.apache.batik.swing.JSVGCanvas;
import org.apache.batik.util.gui.ExtendedGridBagConstraints;
import org.apache.batik.util.gui.resource.ActionMap;
import org.apache.batik.util.gui.resource.ButtonFactory;
import org.apache.batik.util.gui.resource.MissingListenerException;
import org.apache.batik.util.gui.resource.ResourceManager;

/**
 * This class represents a Dialog that lets the user searching for text inside
 * an SVG document.
 *
 * @author <a href="mailto:tkormann@apache.org">Thierry Kormann</a>
 * @version $Id$
 */
public class FindDialog extends JDialog implements ActionMap {

    /**
     * The resource file name
     */
    protected final static String RESOURCES =
        "org.apache.batik.apps.svgbrowser.resources.FindDialog";

    // action names
    public final static String FIND_ACTION = "FindButtonAction";

    public final static String CLEAR_ACTION = "ClearButtonAction";

    public final static String CLOSE_ACTION = "CloseButtonAction";

    /**
     * The resource bundle
     */
    protected static ResourceBundle bundle;

    /**
     * The resource manager
     */
    protected static ResourceManager resources;

    static {
        bundle = ResourceBundle.getBundle(RESOURCES, Locale.getDefault());
        resources = new ResourceManager(bundle);
    }

    /** The button factory */
    protected ButtonFactory buttonFactory;

    /** The GVT root into which text is searched. */
    protected GraphicsNode gvtRoot;

    /** The GVTTreeWalker used to scan the GVT Tree. */
    protected GVTTreeWalker walker;

    /** The current index in the TextNode's string. */
    protected int currentIndex;

    /** The TextField that owns the text to search. */
    protected JTextField search;

    /** The next button. */
    protected JButton findButton;

    /** The next button. */
    protected JButton clearButton;

    /** The cancel button. */
    protected JButton closeButton;

    /** The case sensitive button. */
    protected JCheckBox caseSensitive;

    /** The canvas. */
    protected JSVGCanvas svgCanvas;

    /** The highlight button. */
    protected JRadioButton highlightButton;

    /** The highlight and center button. */
    protected JRadioButton highlightCenterButton;

    /** The highlight center and zoom button. */
    protected JRadioButton highlightCenterZoomButton;
    /**
     * Constructs a new <tt>FindDialog</tt>.
     */
    public FindDialog(JSVGCanvas svgCanvas) {
        this(null, svgCanvas);
    }

    /**
     * Constructs a new <tt>FindDialog</tt>.
     */
    public FindDialog(Frame owner, JSVGCanvas svgCanvas) {
        super(owner, resources.getString("Dialog.title"));
        this.svgCanvas = svgCanvas;

        buttonFactory = new ButtonFactory(bundle, this);

        listeners.put(FIND_ACTION, 
		      new FindButtonAction());

        listeners.put(CLEAR_ACTION, 
		      new ClearButtonAction());

        listeners.put(CLOSE_ACTION, 
		      new CloseButtonAction());

	JPanel p = new JPanel(new BorderLayout());
	p.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
	p.add(createFindPanel(), BorderLayout.CENTER);
	p.add(createShowResultPanel(), BorderLayout.SOUTH);

	getContentPane().add(p, BorderLayout.CENTER);
        getContentPane().add(createButtonsPanel(), BorderLayout.SOUTH);
    }

    /**
     * Creates the Find panel.
     */
    protected JPanel createFindPanel() {
        JPanel panel = new JPanel(new GridBagLayout());

        panel.setBorder(BorderFactory.createTitledBorder
                        (BorderFactory.createEtchedBorder(),
                         resources.getString("Panel.title")));

        ExtendedGridBagConstraints gbc = new ExtendedGridBagConstraints();
        gbc.insets = new Insets(2, 2, 2, 2);

        gbc.anchor = ExtendedGridBagConstraints.EAST;
        gbc.fill = ExtendedGridBagConstraints.NONE;
        gbc.setWeight(0, 0);
        gbc.setGridBounds(0, 0, 1, 1);
        panel.add(new JLabel(resources.getString("FindLabel.text")), gbc);

        gbc.fill = ExtendedGridBagConstraints.HORIZONTAL;
        gbc.setWeight(1.0, 0);
        gbc.setGridBounds(1, 0, 2, 1);
        panel.add(search = new JTextField(20), gbc);

        gbc.fill = ExtendedGridBagConstraints.NONE;
        gbc.anchor = ExtendedGridBagConstraints.WEST;
        gbc.setWeight(0, 0);
        gbc.setGridBounds(1, 1, 1, 1);
        caseSensitive = buttonFactory.createJCheckBox("CaseSensitiveCheckBox");
        panel.add(caseSensitive, gbc);

        return panel;
    }

    protected JPanel createShowResultPanel() {
        JPanel panel = new JPanel(new GridBagLayout());

        panel.setBorder(BorderFactory.createTitledBorder
                        (BorderFactory.createEtchedBorder(),
                         resources.getString("ShowResultPanel.title")));

        ExtendedGridBagConstraints gbc = new ExtendedGridBagConstraints();
        gbc.insets = new Insets(2, 2, 2, 2);

        gbc.anchor = ExtendedGridBagConstraints.WEST;
        gbc.fill = ExtendedGridBagConstraints.NONE;
        gbc.setWeight(0, 0);

	ButtonGroup grp = new ButtonGroup();

	highlightButton = buttonFactory.createJRadioButton("Highlight");
	highlightButton.setSelected(true);
	grp.add(highlightButton);
        gbc.setGridBounds(0, 0, 1, 1);
        panel.add(highlightButton, gbc);

	highlightCenterButton = 
	    buttonFactory.createJRadioButton("HighlightAndCenter");
	grp.add(highlightCenterButton);
        gbc.setGridBounds(0, 1, 1, 1);
        panel.add(highlightCenterButton, gbc);

	highlightCenterZoomButton = 
	    buttonFactory.createJRadioButton("HighlightCenterAndZoom");
	grp.add(highlightCenterZoomButton);
        gbc.setGridBounds(0, 2, 1, 1);
        panel.add(highlightCenterZoomButton, gbc);

	return panel;
    }

    /**
     * Creates the buttons panel
     */
    protected JPanel createButtonsPanel() {
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        panel.add(findButton = buttonFactory.createJButton("FindButton"));
        panel.add(clearButton = buttonFactory.createJButton("ClearButton"));
        panel.add(closeButton = buttonFactory.createJButton("CloseButton"));
        return panel;
    }


    /**
     * Sets the graphics node into which text is searched.
     * @param gvtRoot the GVT root node
     */
    public void setGraphicsNode(GraphicsNode gvtRoot) {
        this.gvtRoot = gvtRoot;
        if (gvtRoot != null) {
            this.walker = new GVTTreeWalker(gvtRoot);
        } else {
            this.walker = null;
        }
    }

    /**
     * Returns the next GraphicsNode that matches the specified string or null
     * if any.
     *
     * @param text the text to match
     */
    protected GraphicsNode getNext(String text) {
	if (walker == null && gvtRoot != null) {
	    walker = new GVTTreeWalker(gvtRoot);
	}
        GraphicsNode gn = walker.getCurrentGraphicsNode();
	int index = match(gn, text, currentIndex+text.length());
	if (index >= 0) {
	    currentIndex = index;
	} else {
	    currentIndex = 0;
	    gn = walker.nextGraphicsNode();
	    while (gn != null && 
		   ((currentIndex = match(gn, text, currentIndex)) < 0)) {
		currentIndex = 0;
		gn = walker.nextGraphicsNode();
	    }
	}
        return gn;
    }

    /**
     * Returns the index inside the specified TextNode of the
     * specified text, or -1 if not found.
     *
     * @param node the graphics node to check
     * @param text the text use to match 
     * @param index the index from which to start */
    protected int match(GraphicsNode node, String text, int index) {
        if (!(node instanceof TextNode)
            || !node.isVisible()
            || text == null || text.length() == 0) {
            return -1;
        }
        String s = ((TextNode)node).getText();
        if (!caseSensitive.isSelected()) {
            s = s.toLowerCase();
            text = text.toLowerCase();
        }
        return s.indexOf(text, index);
    }

    /**
     * Shows the current selected <tt>TextNode</tt>.
     */
    protected void showSelectedGraphicsNode() {
        GraphicsNode gn = walker.getCurrentGraphicsNode();
        if (!(gn instanceof TextNode)) {
            return;
        }
	TextNode textNode = (TextNode)gn;
	// mark the selection of the substring found
	String text    = textNode.getText();
	String pattern = search.getText();
        if (!caseSensitive.isSelected()) {
            text    = text.toLowerCase();
            pattern = pattern.toLowerCase();
        }
	int end = text.indexOf(pattern, currentIndex);

	AttributedCharacterIterator aci = 
	    textNode.getAttributedCharacterIterator();
	aci.first();
	for (int i=0; i < end; ++i) {
	    aci.next();
	}
	Mark startMark = textNode.getMarkerForChar(aci.getIndex(), true);
	
	for (int i = 0; i < pattern.length()-1; ++i) {
	    aci.next();
	}
	Mark endMark = textNode.getMarkerForChar(aci.getIndex(), false);
	svgCanvas.select(startMark, endMark);

	// zoom on the TextNode if needed
        if (highlightButton.isSelected()) {
	    return;
	}

	// get the highlight shape in GVT root (global) coordinate sytem
	Shape s = textNode.getHighlightShape();
	AffineTransform at;
	if (highlightCenterZoomButton.isSelected()) {
	    at = svgCanvas.getInitialTransform();
	} else {
	    at = svgCanvas.getRenderingTransform();
	}
	// get the bounds of the highlight shape in the canvas coordinate system
	Rectangle2D gnb = at.createTransformedShape(s).getBounds();
	    
	Dimension canvasSize = svgCanvas.getSize();
	// translate the highlight region to (0, 0) in the canvas coordinate
	// system
	AffineTransform Tx = AffineTransform.getTranslateInstance
	    (-gnb.getX()-gnb.getWidth()/2,
	     -gnb.getY()-gnb.getHeight()/2);
	
	if (highlightCenterZoomButton.isSelected()) {
	    // zoom on the highlight shape such as the shape takes x% of the
	    // canvas size
	    double sx = canvasSize.width/gnb.getWidth();
	    double sy = canvasSize.height/gnb.getHeight();
	    double scale = Math.min(sx, sy) / 8;
	    if (scale > 1) {
		Tx.preConcatenate
		    (AffineTransform.getScaleInstance(scale, scale));
	    }
	}
	Tx.preConcatenate(AffineTransform.getTranslateInstance
			  (canvasSize.width/2, canvasSize.height/2));
	// take into account the initial transform
	AffineTransform newRT = new AffineTransform(at);
	newRT.preConcatenate(Tx);
	// change the rendering transform
	svgCanvas.setRenderingTransform(newRT);
    }

    // ActionMap implementation

    /**
     * The map that contains the listeners
     */
    protected Map listeners = new HashMap(10);

    /**
     * Returns the action associated with the given string
     * or null on error
     * @param key the key mapped with the action to get
     * @throws MissingListenerException if the action is not found
     */
    public Action getAction(String key) throws MissingListenerException {
        return (Action)listeners.get(key);
    }

    //////////////////////////////////////////////////////////////////////////
    // Action implementation
    //////////////////////////////////////////////////////////////////////////

    /**
     * The action associated to the 'find' button.
     */
    protected class FindButtonAction extends AbstractAction {
        public void actionPerformed(ActionEvent e) {
            String text = search.getText();
	    if (text == null || text.length() == 0) {
		return;
	    }
	    GraphicsNode gn = getNext(text);
	    if (gn != null) {
		showSelectedGraphicsNode();
	    } else {
		// end of document reached
		walker = null;
		JOptionPane.showMessageDialog(FindDialog.this, 
					      resources.getString("End.text"), 
					      resources.getString("End.title"),
					      JOptionPane.INFORMATION_MESSAGE);
	    }
	}
    }

    /**
     * The action associated to the 'clear' button.
     */
    protected class ClearButtonAction extends AbstractAction {
        public void actionPerformed(ActionEvent e) {
	    search.setText(null);
	    walker = null;
        }
    }

    /**
     * The action associated to the 'close' button.
     */
    protected class CloseButtonAction extends AbstractAction {
        public void actionPerformed(ActionEvent e) {
            dispose();
        }
    }
}


