/*
 * Copyright (c) 1997 John Jensen. All rights reserved.
 *
 * This software is FREE FOR COMMERCIAL AND NON-COMMERCIAL USE,
 * provided the following condition is met.
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby granted,
 * provided that any copy or derivative of this software or documentation
 * retaining the name "John Jensen" also retains this condition and the
 * following disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * CopyrightVersion 1.0
 */

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;

public class TextMenu extends MenuBar implements ActionListener
{
	// menus

	private Menu fileMenu;
	private Menu editMenu;
	private Menu fontMenu;
	private Menu sizeMenu;
	private Menu tabsMenu;
	private Menu beanMenu;
	private Menu helpMenu;
	
	// adaptors
	
	private EditMan	editMan;
	private SizeMan	sizeMan;
	private FontMan	fontMan;
	private TabMan	tabMan;

	// allocate standard components of TextEdit as part of initialization:

	private String newString	= new String("New");
	private String openString	= new String("Open");
	private String saveString	= new String("Save");
	private String saveAsString = new String("Save As");
	private String printString	= new String("Print");
	private String quitString	= new String("Quit");
	private String otherString	= new String("Other");
	private String aboutString	= new String("About");

	// remember who our parents are

	private TextEdit textEdit;
	private TextCanvas textCanvas;

	// beans

	private Vector beans;
	private Class sfi;
	private Class tfi;
	
	// constructor puts together UI

	public TextMenu(TextEdit parent, Vector b)
	{		
		super();

		Object o;
		String s;

		textEdit = parent;
		textCanvas = textEdit.getCanvas();
		beans = b;

		try
		{
			sfi = Class.forName("SimpleFilterInterface");
			tfi = Class.forName("Test01FilterInterface");
		}
		catch (ClassNotFoundException e)
		{
			System.out.println("Sorry, menu could not load filter interfaces.");
			beans = null;
		}

		CheckboxMenuItem cbi;
						
		editMan = new EditMan(parent);
		sizeMan = new SizeMan(parent);
		fontMan = new FontMan(parent);
		tabMan = new TabMan(parent);

		fileMenu = new Menu("File");
		fileMenu.add(new MenuItem(newString));
		fileMenu.add(new MenuItem(openString));
		fileMenu.add(new MenuItem(saveString));
		fileMenu.add(new MenuItem(saveAsString));
		fileMenu.addSeparator();
		fileMenu.add(new MenuItem(printString));
		fileMenu.addSeparator();
		fileMenu.add(new MenuItem(quitString));    
		fileMenu.addActionListener(this);        
		add(fileMenu);

		editMenu = new Menu("Edit");
		editMan.addItems(editMenu);
		add(editMenu);

		fontMenu = new Menu("Font");
        String[] fontNames = parent.getToolkit().getFontList();
        for (int i = 0; i < fontNames.length; i++)
		{
			if (fontNames[i].equals("Courier"))
			{
				cbi = add_checked(fontMenu, fontMan, fontNames[i]);
				fontMan.remember(cbi);
			}
			else
			{
				add_unchecked(fontMenu, fontMan, fontNames[i]);
			}
		}
		add(fontMenu);

		sizeMenu = new Menu("Size");
		add_unchecked(sizeMenu, sizeMan, new String("9"));
		add_unchecked(sizeMenu, sizeMan, new String("10"));
		add_unchecked(sizeMenu, sizeMan, new String("11"));
		cbi = add_checked(sizeMenu, sizeMan, new String("12"));
		sizeMan.remember(cbi);
		add_unchecked(sizeMenu, sizeMan, new String("14"));
		add_unchecked(sizeMenu, sizeMan, new String("16"));
		add_unchecked(sizeMenu, sizeMan, new String("18"));
		add_unchecked(sizeMenu, sizeMan, new String("36"));
		add_unchecked(sizeMenu, sizeMan, new String("48"));
		add(sizeMenu);

		tabsMenu = new Menu("Tabs");
		tabMan.addItems(tabsMenu);
		add(tabsMenu);

		beanMenu = new Menu("Options");
		if (beans != null)
			for (int i = 0; i < beans.size(); i++ )
			{
				s = null;
				o = beans.elementAt(i);
				if (sfi.isInstance(o))
					s = ((SimpleFilterInterface)o).getMenuString();
				else
				if (tfi.isInstance(o))
					s = ((Test01FilterInterface)o).getMenuString();
				if (s != null)
					beanMenu.add(new MenuItem(s));
			}
		beanMenu.addActionListener(this);  
		add(beanMenu);

		helpMenu = new Menu("Help");
		helpMenu.add(new MenuItem(aboutString));
		helpMenu.addActionListener(this);        
		add(helpMenu);
	}
	
	private void add_unchecked( Menu menu, ItemListener adaptor, String string )
	{
		CheckboxMenuItem cbi;
		
		cbi = new CheckboxMenuItem(string);
		cbi.addItemListener(adaptor);
		menu.add(cbi);
	}

	private CheckboxMenuItem add_checked( Menu menu, ItemListener adaptor, String string )
	{
		CheckboxMenuItem cbi;
		
		cbi = new CheckboxMenuItem(string);
		cbi.addItemListener(adaptor);
		cbi.setState(true);
		menu.add(cbi);
		
		return cbi;
	}

	// action handler, part of std java event handling

    public void actionPerformed(ActionEvent evt)
	{
		int i;

		Object source = evt.getSource();
		String cmd = evt.getActionCommand();

		if (source == fileMenu)
			doFile(cmd);
		else
		if (source == beanMenu)
			doBean(cmd);
		else
		if (source == helpMenu)
		{
			AboutDialog ab = new AboutDialog(textEdit);
			ab.show();
		}
	}
	
	private void doBean(String cmd)
	{
		int i = 0;
		boolean done = false;
		Object o;

		while (!done && (i < beans.size()))
		{
			o = beans.elementAt(i);
			if (sfi.isInstance(o))
				done = doSimple(cmd, (SimpleFilterInterface)o);
			else
			if (tfi.isInstance(o))
				done = doTest(cmd, (Test01FilterInterface)o);
			i++;
		}
	}

	private boolean doSimple(String cmd, SimpleFilterInterface fi)
	{
		boolean done = false;

		String s = fi.getMenuString();
		if (cmd.equals(s))
		{
			String data = textCanvas.copy(false);
			data = fi.filterText(data);
			if (data != null)
				textCanvas.paste(data);
			done = true;
		}

		return done;
	}

	private boolean doTest(String cmd, Test01FilterInterface fi)
	{
		boolean done = false;

		String s = fi.getMenuString();
		if (cmd.equals(s))
		{
			String data = textCanvas.copy(false);
			data = fi.filterText(textEdit,data);
			if (data != null)
				textCanvas.paste(data);
			done = true;
		}

		return done;
	}

	private void doFile(String cmd)
	{
		if (cmd.equals(newString))
			textEdit.cmdFileNew();
		else
		if (cmd.equals(openString))
			textEdit.cmdFileOpen();
		else
		if (cmd.equals(saveString))
			textEdit.cmdFileSave();
		else
		if (cmd.equals(saveAsString))
			textEdit.cmdFileSaveAs();
		else
		if (cmd.equals(printString))
			textEdit.cmdPrint();
		else
		if (cmd.equals(quitString))
			textEdit.cmdFileQuit();
	}
}

class AboutDialog extends Dialog implements WindowListener, ActionListener
{
	Button ok;

	public AboutDialog(Frame parent)
	{
		super(parent,"About TextEdit",true);

		Panel center = new Panel();
		center.add(new Label("TextEdit v1.05"));
		center.add(new Label("Copyright (c) 1997 John Jensen"));
		center.add(new Label("Contact: jjens@primenet.com"));
		center.add(new Label("All rights reserved"));
		center.add(new Label("This is experimental software,"));
		center.add(new Label("use it at your own risk"));
		add("Center", center);

		Panel p = new Panel();
		ok = new Button("Ok");
		ok.addActionListener(this);
		p.add(ok);
		add("South",p);
		setSize(240,240);

		addWindowListener(this);
	}

	// dispose on 'ok'

    public void actionPerformed(ActionEvent event)
	{
        if (event.getSource() == ok)
			dispose();
	}

	// add the 1.1 WindowListener stuff

    public void windowDeiconified(WindowEvent event) {}
    public void windowIconified(WindowEvent event) {}
    public void windowActivated(WindowEvent event) {}
    public void windowDeactivated(WindowEvent event) {}
    public void windowOpened(WindowEvent event) {}
    public void windowClosed(WindowEvent event) {}

    public void windowClosing(WindowEvent event) {
			dispose();
    }

}

class SizeMan extends Object implements ItemListener
{
	// remember stuff

	private TextEdit textEdit;
	private CheckboxMenuItem lastSize = null;
	
	// constructor puts together UI

	public SizeMan(TextEdit parent)
	{
		textEdit = parent;
	}
	
	public void remember( CheckboxMenuItem item )
	{
		if (lastSize != null)
			lastSize.setState(false);
		lastSize = item;
	}
	
	public void itemStateChanged(ItemEvent evt)
	{
		remember((CheckboxMenuItem)evt.getSource());
		String cmd = (String)evt.getItem();
		Integer size = new Integer(cmd);
		textEdit.setFontSize(size.intValue());
	}
}

final class FontMan extends Object implements ItemListener
{
	// remember stuff

	private TextEdit textEdit;
	private CheckboxMenuItem lastTab = null;
	
	// constructor puts together UI

	public FontMan(TextEdit parent)
	{
		textEdit = parent;
	}
	
	public void remember( CheckboxMenuItem item )
	{
		if (lastTab != null)
			lastTab.setState(false);
		lastTab = item;
	}
	
	public void itemStateChanged(ItemEvent evt)
	{
		String cmd = (String)evt.getItem();
		remember((CheckboxMenuItem)evt.getSource());
		textEdit.setFont(cmd);
	}
}

class TabMan extends Object implements ItemListener, ActionListener
{
	// remember stuff

	private int tabSize = 4;
	private TextEdit textEdit;
	private TabDialog tab;
	private	CheckboxMenuItem tab4;
	private	CheckboxMenuItem tab8;
	private	CheckboxMenuItem tabOther;
	private String otherString	= new String("Other");
	
	// constructor puts together UI

	public TabMan(TextEdit parent)
	{
		textEdit = parent;
	}
	
	public void addItems(Menu menu)
	{
		
		tab4 = new CheckboxMenuItem(new String("4"));
		tab4.addItemListener(this);
		menu.add(tab4);
		tab4.setState(true);

		tab8 = new CheckboxMenuItem(new String("8"));
		tab8.addItemListener(this);
		menu.add(tab8);

		tabOther = new CheckboxMenuItem(new String("Other"));
		tabOther.addItemListener(this);
		menu.add(tabOther);
	}
	
	public void setCheck( int tab )
	{
		tab4.setState(false);
		tab8.setState(false);
		tabOther.setState(false);

		switch(tab){
		case 4:
			tab4.setState(true);
			break;
		case 8:
			tab8.setState(true);
			break;
		default:
			tabOther.setState(true);
			break;
		}
	}
	
	public void itemStateChanged(ItemEvent evt)
	{
		String cmd = (String)evt.getItem();
	
		if (otherString.equals(cmd) == true)
		{
			tab = new TabDialog(textEdit,this);
			tab.show();
		}
		else
		{
			tabSize = new Integer(cmd).intValue();
			textEdit.setTabSize(tabSize);
		}
		setCheck(tabSize);
	}
	
    public void actionPerformed(ActionEvent evt)
	{
		boolean success = true;
		
        String cmd = evt.getActionCommand();
		
		if (cmd.equals("Ok"))
		{
			int tabs = 4;
			try
			{
System.out.println("'" + tab.getTabs() + "'");
				tabs = new Integer(tab.getTabs()).intValue();
				textEdit.setTabSize(tabs);
			}
			catch (Exception e)
			{
				textEdit.getToolkit().beep();
				success = false;
			}
			if (success)
			{
				tabSize = tabs;
				tab.dispose();
			}
		}
		else
		if (cmd.equals("Cancel"))
			tab.dispose();
	}
}

class TabDialog extends Dialog implements WindowListener
{
	Button button;
	TextField tabField;

	public TabDialog(TextEdit parent, ActionListener listener)
	{
		super(parent,"About TextEdit",true);

		Panel p1 = new Panel();
		p1.setLayout(new FlowLayout());
		p1.add(new Label("Tab Size:  "));
		tabField = new TextField(Integer.toString(parent.getTabSize()),3);
		p1.add(tabField);
		add("North", p1);

		Panel p2 = new Panel();
		button = new Button("Ok");
		button.addActionListener(listener);
		p2.add(button);
		button = new Button("Cancel");
		button.addActionListener(listener);
		p2.add(button);
		add("South",p2);
		setSize(220,100);

		addWindowListener(this);
	}
	
	// allow the listener to get the tabField
	
	public String getTabs()
	{
		return tabField.getText();
	}

	// add the 1.1 WindowListener stuff

    public void windowDeiconified(WindowEvent event) {}
    public void windowIconified(WindowEvent event) {}
    public void windowActivated(WindowEvent event) {}
    public void windowDeactivated(WindowEvent event) {}
    public void windowOpened(WindowEvent event) {}
    public void windowClosed(WindowEvent event) {}

    public void windowClosing(WindowEvent event) {
			dispose();
    }

}
