import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/** DemoLookAndFeel - similar to <code>DemoMenu2.java</code>
* but further exploring the
* different 'look and feels' available on the system.<p>
*
* This application uses the following statements to determine which
* LookAndFeel options are available on the system:<p>
*
* <pre>
*     UIManager.LookAndFeelInfo[] laf;
*     laf = UIManager.getInstalledLookAndFeels();
* </pre>
*
* The method <code>getInstalledLookAndFeels</code> is a static method
* in the <code>UIManager</code> class in the <code>javax.swing</code>
* package.  It returns an array of <code>UIManager.LookAndFeelInfo</code>
* objects.  Each object contains information about a LookAndFeel
* implementation available with the installed software development kit.<p>
*
* A <code>View</code> menu is added to the application's menubar with
* as many entries as are contained in the <code>laf</code> array.  The
* label for each entry is obtained via<p>
*
* <pre>
*     laf[i].getName();
* </pre>
*
* When the user selects a LookAndFeel entry from the View menu,
* the current LookAndFeel is changed accordingly.  The specific
* line of code that performs the change is<p>
*
* <pre>
*     UIManager.setLookAndFeel(laf[i].getClassName());
* </pre>
*
* which is followed by<p>
*
* <pre>
*     SwingUtilities.updateComponentTreeUI(this);
* </pre>
*
* to force an update of the application's component tree.
* See the source code for further details.<p> 
*
* Invocations:<p>
*
* Showing output to console upon launching...<br>
* <center><img src="DemoLookAndFeel-1.gif"></center><p>
*
* Showing 'Metal' (Java) look and feel...<br>
* <center><img src="DemoLookAndFeel-2.gif"></center><p>
*
* Showing 'Motif' look and feel...<br>
* <center><img src="DemoLookAndFeel-3.gif"></center><p>
*
* Showing 'Windows' look and feel...<br>
* <center><img src="DemoLookAndFeel-4.gif"></center><p>
*
* @see <a href="DemoLookAndFeel.java">source code</a>
* @author Scott MacKenzie, 2003
*/
public class DemoLookAndFeel
{
   public static void main(String[] args)
   {
      UIManager.LookAndFeelInfo[] laf = UIManager.getInstalledLookAndFeels();
      System.out.println("LookAndFeel implementations installed on this system...");
      for (int i = 0; i < laf.length; ++i)
      {
         System.out.println("-----");
         System.out.println("Name:  " + laf[i].getName());
         System.out.println("Class: " + laf[i].getClassName());
      }
      System.out.println("-----");

      // get this system's default look and feel

      String s = UIManager.getSystemLookAndFeelClassName();
      System.out.println("Default: " + s);
      System.out.println("-----");

      DemoLookAndFeelFrame frame = new DemoLookAndFeelFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setTitle("DemoLookAndFeel");
      frame.pack();
      frame.show();      
   }
}

class DemoLookAndFeelFrame extends JFrame
implements ActionListener, ItemListener
{
   // declare private components
   private JTextField message;
   private JRadioButtonMenuItem serif;
   private JRadioButtonMenuItem sansSerif;
   private JRadioButtonMenuItem monospaced;
   private JRadioButtonMenuItem defaultSize;
   private JMenuItem about;
   private JMenuItem help;
   private JMenuItem color;
   private JMenuItem cancelPopup;
   private JMenuItem changePopup;
   private JMenuItem restorePopup;
   private JPopupMenu popup;
   private JCheckBoxMenuItem italic;
   private JCheckBoxMenuItem bold;

   private JRadioButtonMenuItem[] viewItem; 
   UIManager.LookAndFeelInfo[] laf;
   private JTextField statusField;

   final String DEFAULT_MESSAGE = "Hello Java World ";
   final String DEFAULT_FAMILY = "Serif";
   final int DEFAULT_SIZE = 24;
   final int DEFAULT_STYLE = Font.PLAIN;
   final Font DEFAULT_FONT
      = new Font(DEFAULT_FAMILY, DEFAULT_STYLE, DEFAULT_SIZE);
   final Color DEFAULT_COLOR = Color.blue;

   // constructor

   public DemoLookAndFeelFrame()
   {
      // ----------------------------------
      // construct and configure components
      // ----------------------------------

      message = new JTextField();
      message.setEditable(false);
      message.setFont(DEFAULT_FONT);
      message.setText(DEFAULT_MESSAGE);
      message.setForeground(DEFAULT_COLOR);
      message.setBackground(new Color(255, 231, 231));
      message.setHorizontalAlignment(SwingConstants.CENTER);
      message.setPreferredSize(new Dimension(300, 150));

      // construct menus
      
      JMenuBar menuBar = new JMenuBar();
      this.setJMenuBar(menuBar);

      // File menu (for future consideration)

      JMenu fileMenu = new JMenu("File"); 
      fileMenu.setMnemonic(KeyEvent.VK_F);
      menuBar.add(fileMenu);
      fileMenu.add(new JMenuItem("Unimplemented",
         new ImageIcon("triangle.gif")));

      // Edit menu (for future consideration)

      JMenu editMenu = new JMenu("Edit");  
      editMenu.setMnemonic(KeyEvent.VK_E);
      menuBar.add(editMenu);
      editMenu.add(new JMenuItem("Unimplemented",
         new ImageIcon("triangle.gif")));

      // ------------------------------
      // new stuff for LookAndFeel demo
      // ------------------------------

      // View menu

      JMenu viewMenu = new JMenu("View");
      viewMenu.setMnemonic(KeyEvent.VK_V);
      menuBar.add(viewMenu);

      // add as many entries as LAFs on the system

      laf = UIManager.getInstalledLookAndFeels();
      viewItem = new JRadioButtonMenuItem[laf.length];

      ButtonGroup viewGroup = new ButtonGroup();
      for (int i = 0; i < laf.length; ++i)
      {
         viewItem[i] = new JRadioButtonMenuItem(laf[i].getName());
         viewItem[i].addActionListener(this);
         viewItem[i].setActionCommand(laf[i].getName());
         viewMenu.add(viewItem[i]);
         viewGroup.add(viewItem[i]);
      }

      // use the first LookAndFeel in the array as the default

      viewItem[0].setSelected(true);
      try {
         UIManager.setLookAndFeel(laf[0].getClassName());
      } catch (Exception e)
      {
         System.out.println("Exception: " + e);
      }

      // text field to show statusField LookAndFeel

      JLabel statusLabel = new JLabel("Current look and feel");
      statusField = new JTextField();
      statusField.setPreferredSize(statusLabel.getPreferredSize());
      statusField.setEditable(false);
      statusField.setText(laf[0].getName());

      // Font menu

      JMenu fontMenu = new JMenu("Font");
      fontMenu.setMnemonic(KeyEvent.VK_O);
      menuBar.add(fontMenu);
      serif = new JRadioButtonMenuItem("Serif");
      serif.setMnemonic(KeyEvent.VK_E);
      serif.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_1, ActionEvent.ALT_MASK));

      sansSerif = new JRadioButtonMenuItem("SansSerif");      
      sansSerif.setMnemonic(KeyEvent.VK_A);
      sansSerif.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_2, ActionEvent.ALT_MASK));

      monospaced = new JRadioButtonMenuItem("MonoSpaced");      
      monospaced.setMnemonic(KeyEvent.VK_O);
      monospaced.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_3, ActionEvent.ALT_MASK));

      ButtonGroup familyGroup = new ButtonGroup();
      familyGroup.add(serif);
      familyGroup.add(sansSerif);
      familyGroup.add(monospaced);
      serif.setSelected(true);

      JMenu sizeSubMenu = new JMenu("Size");

      final String[] SZ = { "12", "16", "20", "24", "28", "32", "36", "40", "44" };
      JRadioButtonMenuItem[] sizeButton = new JRadioButtonMenuItem[SZ.length];
      ButtonGroup sizeGroup = new ButtonGroup();
      for (int i = 0; i < SZ.length; ++i)
      {
         sizeButton[i] = new JRadioButtonMenuItem(SZ[i]);
         sizeSubMenu.add(sizeButton[i]);
         sizeButton[i].addActionListener(this);
         sizeGroup.add(sizeButton[i]);
         if (SZ[i].equals("" + DEFAULT_SIZE))
         {
            defaultSize = sizeButton[i];
            defaultSize.setSelected(true);
         }
      }

      italic = new JCheckBoxMenuItem("Italic");      
      bold = new JCheckBoxMenuItem("Bold");

      color = new JMenuItem("Color...");

      fontMenu.add(serif);
      fontMenu.add(sansSerif);
      fontMenu.add(monospaced);
      fontMenu.addSeparator();
      fontMenu.add(sizeSubMenu);
      fontMenu.addSeparator();
      fontMenu.add(italic);
      fontMenu.add(bold);
      fontMenu.addSeparator();
      fontMenu.add(color);

      // Help menu

      JMenu helpMenu = new JMenu("Help");  
      helpMenu.setMnemonic(KeyEvent.VK_H);
      menuBar.add(helpMenu);

      help = new JMenuItem("Help");
      help.setMnemonic(KeyEvent.VK_H);
      help.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0));
      helpMenu.add(help);

      about = new JMenuItem("About DemoLookAndFeel");
      about.setMnemonic(KeyEvent.VK_A);
      about.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A,
         ActionEvent.ALT_MASK));
      helpMenu.add(about);

      // Popup menu (only pops up for right-click on message)

      popup = new JPopupMenu();
      cancelPopup = new JMenuItem("Cancel ");
      changePopup = new JMenuItem("Change message...");
      restorePopup = new JMenuItem("Restore default settings");
      popup.add(cancelPopup);
      popup.add(changePopup);
      popup.add(restorePopup);

      // -------------
      // add listeners
      // -------------

      message.addMouseListener(new PopupListener());
      serif.addActionListener(this);
      sansSerif.addActionListener(this);      
      monospaced.addActionListener(this);
      italic.addItemListener(this);      
      bold.addItemListener(this);
      color.addActionListener(this);
      about.addActionListener(this);
      help.addActionListener(this);
      cancelPopup.addActionListener(this);
      changePopup.addActionListener(this);
      restorePopup.addActionListener(this);
      
      // add components to panel

      JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
      statusPanel.add(statusLabel);
      statusPanel.add(statusField);

      JPanel panel = new JPanel(new BorderLayout());
      panel.add(message, "Center");
      panel.add(statusPanel, "South");

      // make panel this JFrame's content pane

      this.setContentPane(panel);
   }

   // -------------------------------
   // implement ActionListener method
   // -------------------------------

   public void actionPerformed(ActionEvent ae)
   {
      // for in-class demo...
      //System.out.println(ae.paramString());

      JMenuItem source = (JMenuItem)ae.getSource();

      // see if a new look and feel was specified

      for (int i = 0; i < viewItem.length; ++i)
      {
         if (ae.getActionCommand().equals(viewItem[i].getText()))
         {
            try
            {
               UIManager.setLookAndFeel(laf[i].getClassName());
            } catch (Exception e)
            {
               System.out.println("Exception: " + e);
            }
            statusField.setText(laf[i].getName());
            SwingUtilities.updateComponentTreeUI(this);
         }
      }

      String messageText = message.getText();
      Font f = message.getFont();
      String family = f.getName();
      int style = f.getStyle();
      int size = f.getSize();
      Color textColor = message.getForeground();

      if (source == serif) family = "Serif";
      else if (source == sansSerif) family = "SansSerif";
      else if (source == monospaced) family = "Monospaced";
      else if (source.getText().equals("12")) size = 12;
      else if (source.getText().equals("16")) size = 16;
      else if (source.getText().equals("20")) size = 20;
      else if (source.getText().equals("24")) size = 24;
      else if (source.getText().equals("28")) size = 28;
      else if (source.getText().equals("32")) size = 32;
      else if (source.getText().equals("36")) size = 36;
      else if (source.getText().equals("40")) size = 40;
      else if (source.getText().equals("44")) size = 44;
      else if (source == color)
      {
         Color tmp = JColorChooser.showDialog(this,
            "Choose text color", message.getForeground());
         if (tmp != null)
            textColor = tmp;
      }

      // popup menu items
      else if (source == cancelPopup) ; // do nothing
      else if (source == changePopup)
      {
         String tmp = JOptionPane.showInputDialog(message, "Enter new message");
         if (tmp != null && tmp.length() > 0)
            messageText = tmp;
      }
      else if (source == restorePopup)
      {
         messageText = DEFAULT_MESSAGE;
         family = DEFAULT_FAMILY;
         style = DEFAULT_STYLE;
         size = DEFAULT_SIZE;
         textColor = DEFAULT_COLOR;
         italic.setSelected(false);
         bold.setSelected(false);
         serif.setSelected(true);
         defaultSize.setSelected(true);
      }

      if (source == about)
         JOptionPane.showMessageDialog(this,
            "DemoLookAndFeel - A program to demonstrate menus and dialog boxes");
      else if (source == help)
         JOptionPane.showMessageDialog(this,
            "Sorry, you are beyond help!",
            "Help dialog", JOptionPane.INFORMATION_MESSAGE,
            new ImageIcon("yikes.gif"));
      else
      {
         message.setText(messageText);
         message.setFont(new Font(family, style, size));
         message.setForeground(textColor);
      }
   }

   // -----------------------------
   // implement ItemListener method
   // -----------------------------

   public void itemStateChanged(ItemEvent ie)
   {
      // for in-class demo...
      //System.out.println(ie.paramString());

      Object source = ie.getSource();

      Font f = message.getFont();
      String family = f.getName();
      int style = f.getStyle();
      int size = f.getSize();

      if (source == italic)
      {
         if (italic.isSelected())
            style = style | Font.ITALIC;  // turn italics on
         else
            style = style & ~Font.ITALIC; // turn italics off
      }
      else if (source == bold)
      {
         if (bold.isSelected())
            style = style | Font.BOLD;    // turn bold on
         else
            style = style & ~Font.BOLD;   // turn bold off
      }

      // update message
      message.setFont(new Font(family, style, size));
   }

   private class PopupListener extends MouseAdapter
   {
      public void mousePressed(MouseEvent me)
      {
         // for in-class demo...
         //System.out.println(me.paramString());

         // bring up popup window for right click
         if (SwingUtilities.isRightMouseButton(me))
            popup.show(me.getComponent(), me.getX(), me.getY());
      }
   }
}

