package ch.werner_randelshofer.app;/*Copyright (C) 1998-99 Werner Randelshoferwerner.randelshofer@mythen.chhttp://www.mythen.ch/w.randelshofer/    Permission to use this release of MultiShow is herebygranted without fee provided that the complete copyrightnotice and this permission notice appear in all copiesand in supporting documentation.*/import java.awt.*;import java.awt.image.*;import java.awt.event.*;import java.io.*;import java.net.*;import java.util.Vector;import java.util.Properties;import java.util.Enumeration;import ch.werner_randelshofer.gui.MessageDialog;import javax.activation.MailcapCommandMap;import javax.activation.CommandMap;import javax.activation.DataHandler;import javax.activation.CommandObject;import javax.activation.CommandInfo;import javax.activation.FileDataSource;import javax.activation.FileTypeMap;import ch.werner_randelshofer.activation.CTDFileTypeMap;import ch.werner_randelshofer.activation.MultiCTD;import ch.werner_randelshofer.activation.IFFCTD;import ch.werner_randelshofer.activation.URLConnectionCTD;import ch.werner_randelshofer.gui.ViewImage;import ch.werner_randelshofer.util.PropertyModel;/**The MultiShow image viewer application can display imagesof type IFF ILBM, IFF ANIM, GIF and JPEG.@author	Werner Randelshofer, Staldenmattweg 2, CH-6405 Immensee, Switzerland.@version<br>history 0.3.1	1999-04-25			Better support for bogus Java VM's: Always use 8 bits			per pixel for images with IndexColorModel.<br>history	0.3  	1999-03-07			MultiShow is now a generic viewer for the			JavaBeans Activation Framework JAF.<br>history	0.2  	1999-02-07			The File dialog shows now the name of the			Application "MultiShow".			Displays a message when an image can not be loaded.			The frame will be 400x300 pixels wide when			opened with "scrollbars" switched on. (In v0.1			the frame was 0x0 pixels on Windows).			Waits till the image has been loaded completely			before showing it (avoids flickering on Windows).			Screen size was not computed correctly.<br>history	0.1  	1999-02-02			First release.*/public class MultiShowAWTextends Frameimplements ActionListener, ItemListener	{	/* --- instance variables --- */	/** URL of this project. */	private String directory_, filename_;		/** FileDialog instances for this project. */	private FileDialog fd_, settingsFD_;	/** Menu items. */	private CheckboxMenuItem singleProjectUserInterfaceItem_,multiProjectUserInterfaceItem_;	/* --- class variables --- */	/** User Interface Styleguide: TRUE if UI supports multiple projects. */	private static boolean isMultipleProjects_;		/** List of all projects. Needed for multi project UI. */	private static Vector projects_ = new Vector();		/** The current view. */	private Component view_;	/** View properties. */	private PropertyModel propertyModel_;		/** Application properties. */	private static PropertyModel applicationProperties_;		/** View-Menu */	private Menu viewMenu_ = new Menu("View");		/**	Creates a new Project.	*/	public MultiShowAWT()		{		propertyModel_ = (PropertyModel)applicationProperties_.clone();					projects_.addElement(this);		setSize(400,300);				setMenuBar(createMenuBar());				addWindowListener(			new WindowAdapter()				{				public void windowClosing(WindowEvent event)					{					closeProject();					}				}			);		}	public MenuBar createMenuBar()		{		MenuBar mb = new MenuBar();		Menu m = new Menu("Project");		MenuItem mi;		CheckboxMenuItem cmi;		mi = new MenuItem("Open...");		mi.setShortcut(new MenuShortcut(KeyEvent.VK_O));		mi.setActionCommand("open" );		mi.addActionListener(this);		m.add(mi);		mi = new MenuItem("Open Forward");		mi.setShortcut(new MenuShortcut(KeyEvent.VK_F));		mi.setActionCommand("openForward" );		mi.addActionListener(this);		m.add(mi);		mi = new MenuItem("Open Backward");		mi.setShortcut(new MenuShortcut(KeyEvent.VK_B));		mi.setActionCommand("openBackward" );		mi.addActionListener(this);		m.add(mi);		m.add(new MenuItem("-")); //---------------------		if (isMultipleProjects_)			{			mi = new MenuItem("Hide");			mi.setActionCommand("hide");			mi.addActionListener(this);			m.add(mi);			mi = new MenuItem("Reveal...");			mi.setActionCommand("reveal");			mi.addActionListener(this);			m.add(mi);			mi = new MenuItem("Close");			mi.setActionCommand("close");			mi.addActionListener(this);			m.add(mi);			m.add(new MenuItem("-"));//---------------------			}		mi = new MenuItem("About...");		mi.setActionCommand("about");		mi.addActionListener(this);		m.add(mi);		m.add(new MenuItem("-"));//---------------------		mi = new MenuItem("Quit MultiShowAWT");		mi.setShortcut(new MenuShortcut(KeyEvent.VK_Q));		mi.setActionCommand("quit");		mi.addActionListener(this);		m.add(mi);		mb.add(m);		mb.add(viewMenu_);		m = new Menu("Settings");		Menu m2 = new Menu("User Interface");		cmi = new CheckboxMenuItem("Single Project?");		cmi.setActionCommand("singleProjectUserInterface");		cmi.setState(isMultipleProjects_ == false);		cmi.addItemListener(this);		singleProjectUserInterfaceItem_ = cmi;		m2.add(cmi);		cmi = new CheckboxMenuItem("Multiple Projects?");		cmi.setActionCommand("multiProjectUserInterface");		cmi.setState(isMultipleProjects_);		cmi.addItemListener(this);		multiProjectUserInterfaceItem_ = cmi;		m2.add(cmi);		m.add(m2);		m.add(new MenuItem("-"));//---------------------		mi = new MenuItem("Load Settings...");		mi.setActionCommand("loadSettings");		mi.addActionListener(this);		m.add(mi);		mi = new MenuItem("Save Settings");		mi.setActionCommand("saveSettings");		mi.addActionListener(this);		m.add(mi);		mi = new MenuItem("Save Settings As...");		mi.setActionCommand("saveSettingsAs");		mi.addActionListener(this);		m.add(mi);		mb.add(m);				return mb;		}	public void setMultipleProjects(boolean isMulti)		{		if (isMulti == false && projects_.size() != 1)			{			int option = MessageDialog.showConfirmDialog(				this,				"This will close all Projects except\n'" + filename_ + "'.",				"Switch to single project mode.",				MessageDialog.OK_CANCEL_OPTION,				MessageDialog.WARNING_MESSAGE				);			if (option != MessageDialog.OK_OPTION)				{				singleProjectUserInterfaceItem_.setState(false);				multiProjectUserInterfaceItem_.setState(true);				return;				}			}		applyMultipleProjects(isMulti,this);		}	public static void applyMultipleProjects(boolean isMultipleProjects, MultiShowAWT primaryFrame)		{		isMultipleProjects_ = isMultipleProjects;		Enumeration enum = ((Vector)projects_.clone()).elements();		while(enum.hasMoreElements())			{			MultiShowAWT ms = (MultiShowAWT)enum.nextElement();			if ((isMultipleProjects_ == false) && (ms != primaryFrame))				{ ms.dispose(); }			else				{ ms.setMenuBar(ms.createMenuBar()); }			}		}	public void dispose()		{		projects_.removeElement(this);		if (view_ != null && view_ instanceof ViewImage)			{			((ViewImage)view_).setPropertyModel(null);			((ViewImage)view_).flush();			view_ = null;			}		super.dispose();		}	public void itemStateChanged(ItemEvent event)		{		Object source = event.getSource();				if (source == multiProjectUserInterfaceItem_)			{			if (isMultipleProjects_ == false)				{ setMultipleProjects(true); }			}		else if (source == singleProjectUserInterfaceItem_)			{			if (isMultipleProjects_)				{ setMultipleProjects(false); }			}		}	protected void closeProject()		{		if (isMultipleProjects_)			{			Enumeration enum = projects_.elements();			int visibleFrames = 0;			while(enum.hasMoreElements())				{				MultiShowAWT f = (MultiShowAWT)enum.nextElement();				if (f != this && f.isVisible())					{					visibleFrames++;					break;					}				}			if (visibleFrames == 0)				{				int option = MessageDialog.showConfirmDialog(					this,					"Quit MultiShowAWT?",					"Close last Project",					MessageDialog.OK_CANCEL_OPTION,					MessageDialog.QUESTION_MESSAGE					);				if (option == MessageDialog.OK_OPTION)					{ System.exit(0); }				return;				}			else				{ dispose(); }			}		else			{ System.exit(0); }		}	protected void hideProject()		{		if (isMultipleProjects_)			{			Enumeration enum = projects_.elements();			int visibleFrames = 0;			while(enum.hasMoreElements())				{				MultiShowAWT f = (MultiShowAWT)enum.nextElement();				if (f != this && f.isVisible())					{					visibleFrames++;					break;					}				}			if (visibleFrames > 0)				{				setVisible(false);				}			else				{				int option = MessageDialog.showConfirmDialog(					this,					"Quit MultiShowAWT?",					"Hide last Project",					MessageDialog.OK_CANCEL_OPTION,					MessageDialog.QUESTION_MESSAGE					);				if (option == MessageDialog.OK_OPTION)					{ System.exit(0); }				}			}		}	protected void revealProject()		{		if (isMultipleProjects_)			{			Vector invisibles = new Vector();			Enumeration enum = projects_.elements();			while (enum.hasMoreElements())				{				MultiShowAWT f = (MultiShowAWT)enum.nextElement();				if (! f.isVisible())					{ invisibles.addElement(f); }				}			if (invisibles.size() == 0)				{				MessageDialog.showConfirmDialog(this, "Nothing to Reveal.",					"Reveal Project", MessageDialog.DEFAULT_OPTION,MessageDialog.INFORMATION_MESSAGE);				}			else				{				Object[] array = new Object[invisibles.size()];				for (int i = 0; i < invisibles.size(); i++)					{ array[i] = invisibles.elementAt(i); }				MultiShowAWT reveal = (MultiShowAWT)MessageDialog.showInputDialog(this, "Choose one.",						"Reveal Project", MessageDialog.PLAIN_MESSAGE,						array, null);				if (reveal != null)					{ reveal.setVisible(true); 	}				}			}		}		public void actionPerformed(ActionEvent event)		{		String actionCommand = event.getActionCommand();		if (actionCommand.equals("open"))			{			openProject();			}		if (actionCommand.equals("openForward"))			{			openNextProject();			}		if (actionCommand.equals("openBackward"))			{			openPreviousProject();			}		else if (actionCommand.equals("hide"))			{			hideProject();			}		else if (actionCommand.equals("reveal"))			{			revealProject();			}					else if (actionCommand.equals("close"))			{			closeProject();			}		else if (actionCommand.equals("about"))			{			MessageDialog.showConfirmDialog(this,"MultiShowAWT 0.3.1\nŠ 1999 Werner Randelshofer"+(view_ != null ? "\n"+view_.toString() : ""),"About MultiShowAWT",MessageDialog.DEFAULT_OPTION,MessageDialog.PLAIN_MESSAGE);			}		else if (actionCommand.equals("quit"))			{ System.exit(0); }		else if (actionCommand.equals("loadSettings"))			{ loadSettings(); }		else if (actionCommand.equals("saveSettings"))			{ saveSettings(); }		else if (actionCommand.equals("saveSettingsAs"))			{ saveSettingsAs(); }		}	public void setFile(String dir,String filename)		{		filename_ = filename;		directory_ = dir;		setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));		removeAll();		try {			FileDataSource dataSource = new FileDataSource(dir+filename);			dataSource.setFileTypeMap(getFileTypeMap());			DataHandler dataHandler = new DataHandler(dataSource);			CommandInfo commandInfo = dataHandler.getCommand("view");			if (view_ != null && view_ instanceof ViewImage)				{				((ViewImage)view_).setPropertyModel(null);				((ViewImage)view_).flush();				}			viewMenu_.removeAll();			if (commandInfo == null)				{				view_ = null;				add(new Label(dataHandler.getContentType()));				}			else				{				CommandObject commandObject = (CommandObject)commandInfo.getCommandObject(dataHandler,getClass().getClassLoader());				view_ = (Component)commandObject;				if (view_ != null && view_ instanceof ViewImage)					{					((ViewImage)view_).setPropertyModel(propertyModel_);					((ViewImage)view_).addMenuItems(viewMenu_);					}				add(view_);				}			}		catch(ClassNotFoundException e)			{ e.printStackTrace(); }		catch(IOException e)			{ e.printStackTrace(); }		invalidate();		validate();		pack();		setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));		updateTitle();		}			public static FileTypeMap getFileTypeMap()		{		CTDFileTypeMap fileTypeMap = new CTDFileTypeMap();		MultiCTD multiCTD = new MultiCTD();		multiCTD.add(new IFFCTD());		multiCTD.add(new URLConnectionCTD());		fileTypeMap.setCTD(multiCTD);				return fileTypeMap;		}	static		{		MailcapCommandMap mcm = new MailcapCommandMap();		mcm.addMailcap("image/gif; ; x-java-view=ch.werner_randelshofer.gui.ViewImage");		mcm.addMailcap("image/jpeg; ; x-java-view=ch.werner_randelshofer.gui.ViewImage");		mcm.addMailcap("x-iff/ILBM; ; x-java-view=ch.werner_randelshofer.gui.ViewILBM");		mcm.addMailcap("x-iff/ANIM; ; x-java-view=ch.werner_randelshofer.gui.ViewANIM");		CommandMap.setDefaultCommandMap(mcm);		}	public void openProject()		{		if (isMultipleProjects_)			{			MultiShowAWT ms = new MultiShowAWT();			FileDialog fd = new FileDialog(ms,"Select File to Open");			fd.setVisible(true);			if (fd.getFile() != null)				{		    	ms.setFile(fd.getDirectory(),fd.getFile());		    	ms.fd_ = fd;				//ms.setViewSize(viewSizeID_);				/*				Dimension p = getPosition();				p.width += 10;				p.height += 10;		    	ms.setPosition(p);		    	*/		    	ms.setVisible(true);				}			else				{				ms.dispose();				}			}		else			{			if (fd_ == null)				{ fd_ = new FileDialog(this,"Select File to Open"); }			fd_.setVisible(true);			if (fd_.getFile() != null)				{ setFile(fd_.getDirectory(),fd_.getFile()); }			}		}	public void openNextProject()		{		String[] dir = new File(directory_).list();		if (dir == null)			{			getToolkit().beep();			return;			}		sort(dir);		int j = dir.length;		for (int i=0; i < dir.length; i++)			{			if (dir[i].equals(filename_))				{				j = i+1;				break;				}			}		while (j < dir.length)			{			File f = new File(directory_,dir[j]);			if (f.isDirectory())				{ j++; }			else				{ break; }			}		if (j == dir.length)			{			getToolkit().beep();			return;			}		if (isMultipleProjects_)			{			MultiShowAWT ms = new MultiShowAWT();	    	ms.setFile(directory_,dir[j]);	    	ms.setVisible(true);			}		else			{	    	setFile(directory_,dir[j]);			}		}	public void openPreviousProject()		{		String[] dir = new File(directory_).list();		if (dir == null)			{			getToolkit().beep();			return;			}		sort(dir);		int j = -1;		for (int i=0; i < dir.length; i++)			{			if (dir[i].equals(filename_))				{				j = i-1;				break;				}			}		while (j != -1)			{			File f = new File(directory_,dir[j]);			if (f.isDirectory())				{ j--; }			else				{ break; }			}		if (j == -1)			{			getToolkit().beep();			return;			}		if (isMultipleProjects_)			{			MultiShowAWT ms = new MultiShowAWT();	    	ms.setFile(directory_,dir[j]);	    	ms.setVisible(true);			}		else			{	    	setFile(directory_,dir[j]);			}		}    public void loadSettings()    	{    	if (settingsFD_ == null)    		{ settingsFD_ = new FileDialog(this); }		settingsFD_.setTitle("Load Settings");		settingsFD_.setMode(FileDialog.LOAD);		settingsFD_.setVisible(true);		if (settingsFD_.getFile() != null)			{			try {		   		loadProperties(settingsFD_.getDirectory()+settingsFD_.getFile(),this);		   		}		   	catch (IOException e)		   		{		   		MessageDialog.showMessage(this,e.getMessage(),"Load Settings failed");		   		}		   	}    	}    public void saveSettingsAs()    	{    	if (settingsFD_ == null)    		{ settingsFD_ = new FileDialog(this); }		settingsFD_.setTitle("Save Settings");		settingsFD_.setMode(FileDialog.SAVE);		settingsFD_.setVisible(true);		if (settingsFD_.getFile() != null)			{			try {				Enumeration enum = propertyModel_.keys();				while (enum.hasMoreElements())					{					String key = (String)enum.nextElement();					applicationProperties_.put(key,propertyModel_.getProperty(key));					}		   		saveProperties(settingsFD_.getDirectory()+settingsFD_.getFile());		   		}		   	catch (IOException e)		   		{		   		MessageDialog.showMessage(this,e.getMessage(),"Save Settings failed");		   		}		   	}    	}    public void saveSettings()    	{		try {			Enumeration enum = propertyModel_.keys();			while (enum.hasMoreElements())				{				String key = (String)enum.nextElement();				applicationProperties_.put(key,propertyModel_.getProperty(key));				}	   		saveProperties(System.getProperty("user.home")+File.separator+"MultiShowAWT.prefs");	   		}	   	catch (IOException e)	   		{	   		MessageDialog.showMessage(this,e.getMessage(),"Save Settings failed");	   		}    	}    public static void loadProperties(String file, MultiShowAWT primaryFrame)    throws IOException    	{    	applicationProperties_ = new PropertyModel();    	FileInputStream in = null;    	try {	    	in = new FileInputStream(file);	    	applicationProperties_.load(in);			isMultipleProjects_ = "true".equals(applicationProperties_.getProperty("multiProjectUserInterface"));			applyMultipleProjects(isMultipleProjects_, primaryFrame);			}	    finally	    	{	    	if (in != null)	    		{	    		try	{ in.close(); }	    		catch (IOException e) {}	    		}	    	}    	}    public static void saveProperties(String file)    throws IOException    	{    	FileOutputStream out = null;    	try {	    	out = new FileOutputStream(file);			applicationProperties_.put("multiProjectUserInterface",isMultipleProjects_ ? "true":"false");				    	applicationProperties_.save(out,"MultiShowAWT Preferences");			}	    catch (IOException e)	    	{ } // ignore (is this clever or stupid ?).	    finally	    	{	    	if (out != null)	    		{	    		try	{ out.close(); }	    		catch (IOException e) {}	    		}	    	}    	}    public static void main(String[] args)    	{    	try {	    	loadProperties(System.getProperty("user.home")+File.separator+"MultiShowAWT.prefs",null);	    	}	    catch(IOException e) {}    			MultiShowAWT ms = new MultiShowAWT();		FileDialog fd = new FileDialog(ms,"Multishow: Select File to Open");		fd.setVisible(true);		if (fd.getFile() != null)			{	    	ms.setFile(fd.getDirectory(),fd.getFile());	    	ms.fd_ = fd;	    	//ms.setState(Frame.NORMAL);	    	ms.setVisible(true);			}		else			{			System.exit(0);			}    	}    public String toString()    	{    	return filename_;    	}    public void updateTitle()    	{		setTitle(filename_);    	}        protected void sort(String[] array)    	{	    for (int i=0; i < array.length; i++)	    	{			for (int j=i; j>0 && array[j-1].compareTo(array[j]) > 0; j--)				{			    String tmp = array[j-1];			    array[j-1] = array[j];			    array[j] = tmp;				}			}    	}	}