/*-------------------------------------------------------------------------------
Copyright (c)2000 TogetherSoft Corporation. Patents pending. All rights reserved.
-------------------------------------------------------------------------------*/

package com.togethersoft.modules.tutorial;

import com.togethersoft.openapi.ide.IdeContext;
import com.togethersoft.openapi.ide.IdeScript;
import com.togethersoft.openapi.ide.message.IdeMessageManager;
import com.togethersoft.openapi.ide.message.IdeMessageManagerAccess;
import com.togethersoft.openapi.ide.message.IdeMessageType;
import com.togethersoft.openapi.ide.message.IdeMessagePage;
import com.togethersoft.openapi.ide.message.IdeMessageView;
import java.awt.Component;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.ButtonGroup;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.ListSelectionModel;
import javax.swing.ButtonModel;
import javax.swing.ListCellRenderer;
import javax.swing.border.BevelBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * This module shows how to create and use custom message pages.
 * It creates two collaborating message pages. First contains a few control
 * buttons and a text field, where you can enter a message. Then it displays
 * that message in the second page.
 *
 * Actually, there are two purposes of this module:
 * 1. To show how to add a new message page (which can be used not only for
 *    outputting messages - it can contain any components you want! (Page One).
 * 2. To show how to add a new message page with a custom implementation of a
 *    "printMessage" methods (Page Two).
 *
 * This way you learn how to be able to fully customize the output of your
 * modules. Note, you can use the CustomView class as a skeleton for your
 * implementations of message pages with specific ways of printing messages.
 * The details about managing message pages can be found in the description of
 * com.togethersoft.openapi.ide.message package in main API documentation.
 *
 * @author TogetherSoft
 */
public class Lesson10 implements IdeScript, ActionListener
{
   /**
    * Runs this module.
    *
    * @param context the IdeContext instance containing
    * the selection information at the moment the module was called.
    */
    public void run(IdeContext context)
    {
        // printing information message
        IdeMessageManagerAccess.printMessage
            (IdeMessageType.INFORMATION, "Lesson10 module: started");

        // define message type
        messageType = IdeMessageType.INFORMATION;

        // getting message manager
        messageManager = IdeMessageManagerAccess.getMessageManager();

        // creating pages
        createPageOne();
        createPageTwo();

        // setting active page
        messageManager.setActivePage(pageOne);

        // making message pane visible
        IdeMessageManagerAccess.getMessageManager().setPaneVisible(true);

        // printing final information message
        IdeMessageManagerAccess.printMessage
            (IdeMessageType.INFORMATION, "Lesson10 module: finished");
    }

    /**
     * Action handler.
     *
     * @param e ActionEvent object
     */
    public void actionPerformed(ActionEvent e)
    {
        // close command
        if (CLOSE_COMMAND.equals(e.getActionCommand()))
        {
            messageManager.closePage(pageOne);
            messageManager.closePage(pageTwo);
            return;
        }

        // print command
        if (PRINT_MESSAGE_COMMAND.equals(e.getActionCommand()))
        {
            // finding page
            IdeMessagePage pageForOutput = messageManager.findPage(PAGE_TWO_ID);

            // checking if PageTwo was found
            if (pageForOutput == null)
            {
                // create page again
                createPageTwo();
                pageForOutput = messageManager.findPage(PAGE_TWO_ID);
            }

            // Note: we use only standard API methods to output a message in Page Two.
            // You can create your own message pages with your personal methods
            // for displaying messages!
            pageForOutput.printMessage(messageType, textField.getText());
            messageManager.setActivePage(pageForOutput); // making page active
            return;
        }
    }

    /**
     * Creates first message page (PageOne).
     */
    private void createPageOne()
    {
        // creation visual components
        GridBagLayout gridbag = new GridBagLayout();
        GridBagConstraints c = new GridBagConstraints();
        JPanel panelOne = new JPanel();
        panelOne.setLayout(gridbag);
        JButton closeB = new JButton("Remove pages");
        closeB.setToolTipText("Removes this page and Page Two");
        closeB.setActionCommand(CLOSE_COMMAND);
        closeB.addActionListener(this);
        c.gridy = 0;
        c.gridx = 0;
        gridbag.setConstraints(closeB, c);
        panelOne.add(closeB);
        textField =
            new JTextField("  Enter your message here, then press `Print this message` button  ");
        textField.setToolTipText
            ("We will use our custom implementation of `printMessage` method in Page Two to display this message.");
        textField.setMinimumSize(textField.getPreferredSize());
        c.gridx = 1;
        gridbag.setConstraints(textField, c);
        panelOne.add(textField);
        JButton sendB = new JButton("Print this message in Page Two");
        sendB.setActionCommand(PRINT_MESSAGE_COMMAND);
        sendB.addActionListener(this);
        GridBagConstraints e = new GridBagConstraints();
        c.gridx = 2;
        gridbag.setConstraints(sendB, c);
        panelOne.add(sendB);
        JPanel radioButtonsPanel = new JPanel();
        radioButtonsPanel.setToolTipText("Please select the type of your message.");
        ButtonGroup messageTypeGroup = new ButtonGroup();
        JRadioButton informationRadio = new JRadioButton(" Information");
        informationRadio.setToolTipText("Please select the type of your message.");
        informationRadio.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e1) {
                analyzeState(e1, IdeMessageType.INFORMATION);
            }
        });
        radioButtonsPanel.add(informationRadio);
        messageTypeGroup.add(informationRadio);
        JRadioButton warningRadio = new JRadioButton(" Warning");
        warningRadio.setToolTipText("Please select the type of your message.");
        warningRadio.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e2) {
                analyzeState(e2, IdeMessageType.WARNING);
            }
        });
        radioButtonsPanel.add(warningRadio);
        messageTypeGroup.add(warningRadio);
        JRadioButton errorRadio = new JRadioButton(" Error");
        errorRadio.setToolTipText("Please select the type of your message.");
        errorRadio.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e3) {
                analyzeState(e3, IdeMessageType.ERROR);
            }
        });
        radioButtonsPanel.add(errorRadio);
        messageTypeGroup.add(errorRadio);
        messageTypeGroup.setSelected(informationRadio.getModel(), true);
        radioButtonsPanel.setBorder(BorderFactory.createEtchedBorder());
        GridBagConstraints f = new GridBagConstraints();
        f.gridy = 1;
        f.gridx = 1;
        f.gridwidth = 2;
        f.fill = GridBagConstraints.HORIZONTAL;
        gridbag.setConstraints(radioButtonsPanel, f);
        panelOne.add(radioButtonsPanel);
        JScrollPane jPaneOne = new JScrollPane(panelOne);

        // opening page
        pageOne = messageManager.openPage(PAGE_ONE_ID, jPaneOne, null);
        pageOne.setTitle(PAGE_ONE_ID);
    }

    /**
     * Creates second message pane (PageTwo).
     */
    private void createPageTwo()
    {
        // creation visual components
        JPanel panelTwo = new JPanel();
        JList messageArea = new JList(new DefaultListModel());
        messageArea.setCellRenderer(new MyListCellRndrr());
        messageArea.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        panelTwo.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
        panelTwo.add(messageArea);
        JScrollPane jPaneTwo = new JScrollPane(panelTwo);

        // open page
        pageTwo = messageManager.openPage
            (PAGE_TWO_ID, jPaneTwo, new CustomView(messageArea));
        pageTwo.setTitle(PAGE_TWO_ID);
    }

    /**
     * Analyzes state
     *
     * @param e ChangeEvent object
     * @param type type of message
     */
    private void analyzeState(ChangeEvent e, int type)
    {
        JRadioButton b = (JRadioButton)e.getSource();
        ButtonModel m = b.getModel();
        if (m.isSelected()) { messageType = type; }
    }

    private final static String PAGE_ONE_ID = "Page One";
    private final static String PAGE_TWO_ID = "Page Two";
    private final static String CLOSE_COMMAND = "close";
    private final static String PRINT_MESSAGE_COMMAND = "print message";

    private int messageType;
    private IdeMessageManager messageManager;
    private IdeMessagePage pageOne;
    private IdeMessagePage pageTwo;
    private JTextField textField;

    /**
     * This class is a sample of creating your own ways to output messages.
     */
    private class CustomView implements IdeMessageView
    {
        /**
         * Creates a class instance with specified JList object.
         *
         * @param target JList object
         * @see javax.swing.JList
         */
        public CustomView(JList target)
        {
            myTarget = target;
            myTargetModel = (DefaultListModel)myTarget.getModel();
        }

        /**
         * Prints message.
         *
         * @param type message type
         * @param text message text
         * @param sourceURL source URL
         * @param helpURL URL
         */
        public void printMessage
            (int type, String text, String sourceURL, String helpURL)
        {
            printMessage(type, text, sourceURL, helpURL);
        }

        /**
         * Prints message.
         *
         * @param type message type
         * @param text message text
         */
        public void printMessage(int type, String text)
        {
            Font font = null;      // message text font
            Color color = null;    // message text color
            String prefix = null;; // prefix for message

            // check message type
            switch (type)
            {
                case IdeMessageType.INFORMATION: // information message
                    font = new Font("Arial", Font.PLAIN, 22);
                    color = Color.green.darker().darker();
                    prefix = "";
                    break;
                case IdeMessageType.WARNING: // warning message
                    font = new Font("TimesRoman", Font.ITALIC, 22);
                    color = Color.blue;
                    prefix = "Warning:";
                    break;
                case IdeMessageType.ERROR:  // error messsage
                    font = new Font("TimesRoman", Font.BOLD, 35);
                    color = Color.red;
                    prefix = "Error:";
                    break;
            }

            // printing message
            MyLabel label = new MyLabel(prefix + text, color, Color.white);
            label.setFont(font);
            myTargetModel.addElement(label);
            myTarget.setSelectedIndex(myTargetModel.getSize() - 1);
            myTarget.ensureIndexIsVisible(myTarget.getSelectedIndex());
        }

        private JList myTarget;
        private DefaultListModel myTargetModel;
    }

    /**
    * This class is a sample of creating your own Label object.
    */
    private class MyLabel extends JLabel
    {
        /**
         * Creates a class instance with specified parameters.
         *
         * @param text label text
         * @param fc foreground color
         * @param bc background color
         */
        public MyLabel(String text, Color fc, Color bc)
        {
            super(text);
            this.setOpaque(true);
            this.setForeground(fc);
            this.setBackground(bc);
            myFC = fc;
            myBC = bc;
        }

        /**
         * Restores setted before colors.
         */
        public void restoreColors()
        {
            this.setForeground(myFC);
            this.setBackground(myBC);
        }

        private Color myFC; // foreground color
        private Color myBC; // background color
    }

    /**
     * Displays an entry in a list.
     * @see javax.swing specification
     */
    private class MyListCellRndrr implements ListCellRenderer
    {
        public Component getListCellRendererComponent
            (JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
        {
            MyLabel message = (MyLabel)value;
            if (isSelected)
            {
                message.setBackground(list.getSelectionBackground());
            }
            else
            {
                message.restoreColors();
            }
            return message;
        }
    }
}




