/*
 *  ====================================================================
 *  DemoTextLayout1.java : This applet demonstrates how to use geometric
 *  (affine) transformations on text using the text layout support in
 *  Java 2D. The applet displays a text string and a set of sliders to
 *  translate, rotate, scale, and shear the text string.
 *
 *  Note. When a new affine transform is applied to text, it results in
 *  a new derived font (i.e., a new derived font results from a slider
 *  setting).
 *
 *  Adapted from : Pantham S., Pure JFC Swing, 1999.
 *  Modified by : Mark Austin                                March, 2001
 *  ====================================================================
 */

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;

public class DemoTextLayout1 extends JApplet {
    DemoTextLayout1DisplayPanel displayPanel;
    JSlider slider, slider1, slider2, slider3,
            slider4, slider5, slider6, slider7,
            slider8, slider9;

    // Translation distances in x- and y- directions
    double transX = 0.0, transY = 0.0;
    // Rotation parameters: Theta and center of rotation.
    double rotateTheta = 0.0, rotateX = 150.0, rotateY = 150.0;
    // Scale factors in the x- and y- directions
    double scaleX = 1.0, scaleY = 1.0;
    // Shear factors in the x- and y- directions
    double shearX = 0.0, shearY = 0.0 ;

    public void init() {

        // 1. Get the content pane and assign layout

        Container container = getContentPane();

        // 2. Add a control panel with titled border

        JPanel controlPanel = new JPanel();
        controlPanel.setLayout( new GridLayout(4, 3) );
        container.add(controlPanel, BorderLayout.NORTH);
        TitledBorder border = new TitledBorder("Control Panel"); 
        controlPanel.setBorder(border);                         

        // 3. Add various controls to the panel to adjust translation,
        //    rotation, scaling and shearing.

        JLabel label1 = new JLabel("Translate(dx,dy): ");
        JLabel label2 = new JLabel("Rotate(Theta,ox,oy): ");
        JLabel label3 = new JLabel("Scale(sx,sy)x10E-2:");
        JLabel label4 = new JLabel("Shear(shx, shy)X10E-2: ");

        // To control translation 

        controlPanel.add(label1);
        setSlider(controlPanel, JSlider.HORIZONTAL,
                  0, 300, 150, 100, 50);
        slider1 = slider;
        setSlider(controlPanel, JSlider.HORIZONTAL,
                  0, 300, 150, 100, 50);
        slider2 = slider;

        // To control rotation

        controlPanel.add(label2);
        setSlider(controlPanel, JSlider.HORIZONTAL,
                  0, 360, 0, 90, 45);
        slider3 = slider;

        JPanel subPanel = new JPanel();
        subPanel.setLayout(new GridLayout(1, 2));

        setSlider(subPanel, JSlider.HORIZONTAL,
                  0, 300, 150, 150, 50);
        slider4 = slider;
        setSlider(subPanel, JSlider.HORIZONTAL,
                  0, 300, 150, 150, 50);
        slider5 = slider;
        controlPanel.add(subPanel);

        // To control scaling

        controlPanel.add(label3);
        setSlider(controlPanel, JSlider.HORIZONTAL,
                  0, 200, 100, 100, 10);
        slider6 = slider;
        setSlider(controlPanel, JSlider.HORIZONTAL,
                  0, 200, 100, 100, 10);
        slider7 = slider;

        // To control shearing

        controlPanel.add(label4);
        setSlider(controlPanel, JSlider.HORIZONTAL,
                  -100, 100, 0, 100, 25);
        slider8 = slider;
        setSlider(controlPanel, JSlider.HORIZONTAL,
                  -100, 100, 0, 100, 25);
        slider9 = slider;

        // 4. Add the display panel to the frame.

        displayPanel = new DemoTextLayout1DisplayPanel();
        container.add(displayPanel);
    }

    // 5. Creates a slider object with the required tick marks

    public void setSlider(JPanel panel, int orientation,
                          int minimumValue, int maximumValue,
                          int initValue,
                          int majorTickSpacing,
                          int minorTickSpacing) {
        slider = new JSlider(orientation,
                             minimumValue, maximumValue,
                             initValue);
        slider.setPaintTicks(true);
        slider.setMajorTickSpacing(majorTickSpacing);
        slider.setMinorTickSpacing(minorTickSpacing);
        slider.setPaintLabels(true);
        slider.addChangeListener(new SliderListener());
        panel.add(slider);
    }

    // 6. Slider listener class; Methods retrive the values from
    //    the sliders and assign them to the respective parameters.
    //    These parameters are used to apply to the font rendering context.
    //    Next call the repaint() method on canvas.

    class SliderListener implements ChangeListener {
        public void stateChanged(ChangeEvent e) {
            JSlider tempSlider = (JSlider) e.getSource();

            if (tempSlider.equals(slider1)) {
                transX = slider1.getValue()-150.0;
                displayPanel.repaint();
            }
            else if (tempSlider.equals(slider2)) {
                transY = slider2.getValue()-150.0;
                displayPanel.repaint();
            }
            else if (tempSlider.equals(slider3)) {
                rotateTheta = slider3.getValue()*Math.PI/180;
                displayPanel.repaint();
            }
            else if (tempSlider.equals(slider4)) {
                rotateX = slider4.getValue();
                displayPanel.repaint();
            }
            else if (tempSlider.equals(slider5)) {
                rotateY = slider5.getValue();
                displayPanel.repaint();
            }
            else if (tempSlider.equals(slider6)) {
                if (slider6.getValue() != 0.0) {
                    scaleX = slider6.getValue()/100.0;
                    displayPanel.repaint();
                }
            }
            else if (tempSlider.equals(slider7)) {
                if (slider7.getValue() != 0.0) {
                    scaleY = slider7.getValue()/100.0;
                    displayPanel.repaint();
                }
            }
            else if (tempSlider.equals(slider8)) {
                shearX = slider8.getValue()/100.0;
                displayPanel.repaint();
            }
            else if (tempSlider.equals(slider9)) {
                shearY = slider9.getValue()/100.0;
                displayPanel.repaint();
            }
        }
    }

    // 7. Definition of the display panel

    class DemoTextLayout1DisplayPanel extends JPanel {

        // Constructor

        public DemoTextLayout1DisplayPanel() {
            setBackground(Color.white);
        }

        // The update method...
        public void update(Graphics g) {
            g.clearRect(0, 0, getWidth(), getHeight());
            paintComponent(g);
        }

        // The painting method...
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2D = (Graphics2D) g;

            // Assign the translation, rotation, scaling and shearing
            // to the affine transform.

            AffineTransform af = new AffineTransform();
            af.translate(transX, transY);
            af.rotate(rotateTheta, rotateX, rotateY);
            af.scale(scaleX, scaleY);
            af.shear(shearX, shearY);

            // Apply the affine transform to a fort rendering context.

            FontRenderContext frc =  new FontRenderContext(af, false, false);
            Font font = new Font("Dialog", Font.PLAIN, 36);

            // Assign the font and font rendering context to a text layout

            TextLayout layout = new TextLayout("Java 2D Text Layout", font, frc);
            layout.draw(g2D, 25, 75); // draw the layout string
        }
    }
}