Subversion Repositories wimsdev

Rev

Rev 7246 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*    Sketch Elements: Chemistry molecular diagram drawing tool.
  2.    
  3.     (c) 2007 Dr. Alex M. Clark
  4.    
  5.     Released as GNUware, under the Gnu Public License (GPL)
  6.    
  7.     See www.gnu.org for details.
  8. */
  9.  
  10. package WIMSchem;
  11.  
  12. import WIMSchem.ds.*;
  13.  
  14. import java.io.*;
  15. import java.awt.*;
  16. import java.util.*;
  17. import java.awt.image.*;
  18. import java.awt.event.*;
  19. import java.awt.datatransfer.*;
  20. import javax.swing.*;
  21.  
  22. /*
  23.     Encapsulates the editing panel, provides menus and toolbars, and responds to various types
  24.     of events.
  25.    
  26.     few other miscellaneous useful tasks. Is generally intended for using in conjunction with various computational or presentation
  27.     packages which do not themselves necessarily have a good editor for molecular connection graphs.
  28. */
  29.  
  30.  
  31. public class MainPanel extends JPanel implements ActionListener, MouseListener, WindowListener, KeyListener, ClipboardOwner,
  32.                                                   TemplSelectListener, MolSelectListener
  33. {
  34.     public static final String LICENSE= // (encoded in a string so that it appears in the final .jar file)
  35.         "This program is free software; you can redistribute it and/or modify\n"+
  36.         "it under the terms of the GNU General Public License as published by\n"+
  37.         "the Free Software Foundation; either version 2 of the License, or\n"+
  38.         "(at your option) any later version.\n\n"+
  39.         "This program is distributed in the hope that it will be useful,\n"+
  40.         "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"+
  41.         "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"+
  42.         "GNU General Public License for more details.\n\n"+
  43.         "You should have received a copy of the GNU General Public License\n"+
  44.         "along with this program; if not, write to the Free Software\n"+
  45.         "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n"+
  46.         "or see http://www.gnu.org for details.";
  47.  
  48.     public static final String VERSION="SketchEl 1.21 WIMSversion 0.2 SVG export";
  49.     private JFrame frameParent;
  50.     public ImageIcon mainIcon=null,mainLogo=null;
  51.     private static final int TOOL_CURSOR=0;
  52.     private static final int TOOL_ROTATOR=1;
  53.     private static final int TOOL_ERASOR=2;
  54.     private static final int TOOL_DIALOG=3;
  55.     private static final int TOOL_EDIT=4;
  56.     private static final int TOOL_SETATOM=5;
  57.     private static final int TOOL_SINGLE=6;
  58.     private static final int TOOL_DOUBLE=7;
  59.     private static final int TOOL_TRIPLE=8;
  60.     private static final int TOOL_ZERO=9;
  61.     private static final int TOOL_INCLINED=10;
  62.     private static final int TOOL_DECLINED=11;
  63.     private static final int TOOL_UNKNOWN=12;
  64.     private static final int TOOL_CHARGE=13;
  65.     private static final int TOOL_UNDO=14;
  66.     private static final int TOOL_REDO=15;
  67.     private static final int TOOL_TEMPLATE=16;
  68.     private static final int TOOL_CUT=17;
  69.     private static final int TOOL_COPY=18;
  70.     private static final int TOOL_PASTE=19;
  71.     private static final int TOOL_SELECT=20;
  72.     private static final int TOOL_UNSELECT=21;
  73.     public static int        TOOL_COUNT=22;
  74.     public String myAtoms[];
  75.     public boolean ATOM_BUTTONS = false;
  76.     private Properties translation;
  77.     public int MENU_COUNT=8;
  78.     private static final String[] IMAGE_TOOL={"Cursor","Rotator","Erasor","EDialog","AEdit",
  79.     "ASelect","BSingle","BDouble","BTriple","BZero",
  80.     "BInclined","BDeclined","BUnknown","ACharge","Undo",
  81.     "Redo","Template","ECut","ECopy","EPaste","Select","UnSelect","BUnknown","BUnknown"};
  82.     public static boolean[] TOOL_SELECTION={true,true,true,false,true,true,true,true,true,true,
  83.                                         true,true,true,true,false,false,true,false,false,false,false,false};
  84.     public static boolean[] MENU_SELECTION={true,true,true,true,true,true,true,true};
  85.     private AbstractButton[] atomlistButtons;
  86.     private ButtonGroup atomlistGroup;
  87.     private AbstractButton[] toolButtons;
  88.     private ButtonGroup toolGroup;
  89.     private ImageIcon[] toolIcons;
  90.     public EditorPane editor;
  91.     private Templates templ;
  92.     private JCheckBoxMenuItem chkShowHydr,chkShowSter;
  93.     private DraggableMolecule dragMol=null;
  94.     private boolean firstResize=true;
  95.     private String filename=null;
  96.     private String lastElement=null,typedElement="";
  97.     private Molecule lastTemplate=null;
  98.     private int templateIdx=-1;
  99.     public static boolean appletMode=false;
  100.     private boolean streamMode=false,slaveMode=false;
  101.     private boolean useLocalClipboard=false;
  102.     private String appletClipboard="";
  103.     private SaveListener saver=null;
  104.     public final static int MODE_NORMAL=0; // usual invocation, with a frame, and a current file
  105.     public final static int MODE_STREAM=1; // molecule flow-through editing, from stdin to stdout
  106.     public final static int MODE_APPLET=2; // embedded applet version, with no frame
  107.     public final static int MODE_SLAVE=3; // non-file version, editing a transient datastructure
  108.  
  109.     public MainPanel(String LoadFN,int Mode,JFrame FrameParent)
  110.     {
  111.         streamMode=Mode==MODE_STREAM;
  112.         appletMode=Mode==MODE_APPLET;
  113.         slaveMode=Mode==MODE_SLAVE;
  114.         frameParent=FrameParent;
  115.         if(appletMode){
  116.          translation = loadProperties((MainApplet.language).toString());
  117.          TOOL_SELECTION = MainApplet.TOOL_SELECTION;
  118.          TOOL_COUNT = TOOL_SELECTION.length;
  119.          MENU_SELECTION = MainApplet.MENU_SELECTION;
  120.          MENU_COUNT = MENU_SELECTION.length;
  121.          myAtoms = MainApplet.myAtoms;
  122.          ATOM_BUTTONS = MainApplet.ATOM_BUTTONS;
  123.          mainIcon=new ImageIcon(getClass().getResource("/images/wims_icon.gif"));
  124.          mainLogo=new ImageIcon(getClass().getResource("/images/wims_logo.gif"));
  125.         }
  126.         else
  127.         {
  128.             for(int i = 0 ;i < TOOL_COUNT ; i++){ TOOL_SELECTION[i] = true; }
  129.             mainIcon=new ImageIcon(getClass().getResource("/images/MainIcon.png"));
  130.             mainLogo=new ImageIcon(getClass().getResource("/images/MainLogo.png"));
  131.             translation = loadProperties("en");
  132.         }
  133.         if(myAtoms == null ){ myAtoms = new String[] {"C","N","O","H","F","Cl","Br","I","S","P","Na","K","Mg","Ca","Fe","Si"}; }
  134.         useLocalClipboard=appletMode; // applet mode always uses "local clipboard"; if the applet is signed, this will need to switch
  135.                                       // to false if permission has been granted to use the system clipboard
  136.        
  137.  
  138.  
  139.  
  140.         templ=new Templates(getClass());
  141.  
  142.         /* list of atoms in row , like ketcher */
  143.         int num_atoms = myAtoms.length;
  144.         JToolBar atomlist = new JToolBar(JToolBar.HORIZONTAL);
  145.         atomlist.setFloatable(true);
  146.         atomlistButtons = new AbstractButton[num_atoms];
  147.         atomlistGroup = new ButtonGroup();
  148.         Font f = new Font("Dialog", Font.PLAIN, 24);
  149.         atomlist.setFont(f);
  150.        
  151.         /* show a button bar with atoms if the main tool was activated via params*/
  152.         if( ATOM_BUTTONS && appletMode && TOOL_SELECTION[TOOL_SETATOM] ){
  153.             for(int n=0 ; n < num_atoms ;n++ ){
  154.                 atomlistButtons[n]=new JButton(myAtoms[n]);
  155.                 atomlistGroup.add(atomlistButtons[n]);
  156.                 atomlist.add(atomlistButtons[n]);
  157.                 atomlistButtons[n].addActionListener(this);
  158.                 atomlistButtons[n].setToolTipText("element"+myAtoms[n]);    
  159.                 atomlistButtons[n].setBorderPainted(false);
  160.             }
  161.         }
  162.        
  163.  
  164.         // toolbar
  165.        
  166.         JToolBar tools = new JToolBar(JToolBar.VERTICAL);
  167.         tools.setFloatable(true);
  168.         toolButtons=new AbstractButton[TOOL_COUNT];
  169.         toolIcons=new ImageIcon[TOOL_COUNT];
  170.         toolGroup=new ButtonGroup();
  171.         for (int n=0;n<TOOL_COUNT;n++){
  172.           if(TOOL_SELECTION[n]){
  173.            toolIcons[n]=new ImageIcon(getClass().getResource("/images/"+IMAGE_TOOL[n]+".png"));
  174.            toolButtons[n]=new ToolButton(toolIcons[n]);
  175.            toolGroup.add(toolButtons[n]);
  176.            tools.add(toolButtons[n]);
  177.            toolButtons[n].addActionListener(this);
  178.            toolButtons[n].setToolTipText(getToolTips(n));
  179.          }
  180.         }
  181.         if( TOOL_SELECTION[TOOL_CURSOR] ){ toolGroup.setSelected(toolButtons[TOOL_CURSOR].getModel(),true);}
  182.         if( TOOL_SELECTION[TOOL_SETATOM] ){ toolButtons[TOOL_SETATOM].addMouseListener(this);toolButtons[TOOL_SETATOM].addKeyListener(this);selectElement("C");}
  183.         if( TOOL_SELECTION[TOOL_TEMPLATE] ){ toolButtons[TOOL_TEMPLATE].addMouseListener(this);}
  184.            
  185.         // menu
  186.        
  187.         JMenuBar menubar=appletMode ? menuBarApplet() : menuBarApplication();
  188.  
  189.         // molecule
  190.        
  191.         editor=new EditorPane();
  192.         editor.setMolSelectListener(this);
  193.         editor.enableDnD();
  194.         JScrollPane scroll=new JScrollPane(editor);
  195.  
  196.         // overall layout
  197.  
  198.         if (!appletMode)
  199.         {
  200.             setLayout(new BorderLayout());
  201.             add(scroll,BorderLayout.CENTER);
  202.             add(menubar,BorderLayout.NORTH);
  203.             add(tools,BorderLayout.WEST);
  204.         }
  205.         else
  206.         {
  207.             // (!! add a little icon somewhere which does the About box...)
  208.  
  209.             JPanel p=new JPanel();
  210.             p.setLayout(new BorderLayout());
  211.             p.add(menubar,BorderLayout.NORTH);
  212.            
  213.             setLayout(new BorderLayout());
  214.             add(tools,BorderLayout.WEST);
  215.             if( ATOM_BUTTONS ){ add(atomlist,BorderLayout.SOUTH); }
  216.             add(scroll,BorderLayout.EAST);
  217.             add(p,BorderLayout.CENTER);
  218.             p.add(scroll,BorderLayout.CENTER);
  219.         }
  220.        
  221.         editor.grabFocus();
  222.        
  223.         editor.setToolCursor();
  224.        
  225.         if (LoadFN!=null)
  226.         {
  227.             try
  228.             {
  229.                 FileInputStream istr=new FileInputStream(LoadFN);
  230.                 Molecule frag=MoleculeStream.readUnknown(istr);
  231.                 editor.addArbitraryFragment(frag);
  232.                 istr.close();
  233.             }
  234.             catch (IOException e)
  235.             {
  236.                 JOptionPane.showMessageDialog(null,e.toString(),"Open Failed",JOptionPane.ERROR_MESSAGE);
  237.                 return;
  238.             }
  239.  
  240.             setFilename(LoadFN);
  241.             editor.notifySaved();
  242.         }
  243.         if (streamMode) readStream();
  244.        
  245.         addKeyListener(this);
  246.         editor.addKeyListener(this);
  247.         if (frameParent!=null) frameParent.addWindowListener(this);
  248.  
  249.         if (!appletMode)
  250.         {      
  251.             dragMol=new DraggableMolecule(editor);
  252.             menubar.add(dragMol);
  253.         }
  254.     }
  255.    
  256.     // if specified, this interface will hijack all user efforts to "Save" to the source file
  257.     public void setSaveListener(SaveListener saver) {this.saver=saver;}
  258.    
  259.     // builds and returns a menu bar suitable for the application-style invocation
  260.     private JMenuBar menuBarApplication()
  261.     {
  262.         JMenuBar menubar=new JMenuBar();
  263.                
  264.         JMenu menufile=new JMenu(translation.getProperty("File"));
  265.         menufile.setMnemonic(KeyEvent.VK_F);
  266.         menufile.add(menuItem(translation.getProperty("New"),KeyEvent.VK_N,null,KeyStroke.getKeyStroke('N',InputEvent.CTRL_MASK)));
  267.         menufile.add(menuItem(translation.getProperty("New_Window"),KeyEvent.VK_W,null,KeyStroke.getKeyStroke('N',InputEvent.CTRL_MASK+InputEvent.SHIFT_MASK)));
  268.         if (DataWindow.ALLOW) // (temporary)
  269.             menufile.add(menuItem(translation.getProperty("New_DataSheet"),KeyEvent.VK_D,null));
  270.         menufile.add(menuItem(translation.getProperty("Open"),KeyEvent.VK_O,null,KeyStroke.getKeyStroke('O',InputEvent.CTRL_MASK)));
  271.         if (!streamMode) menufile.add(menuItem(translation.getProperty("Save"),KeyEvent.VK_S,null,KeyStroke.getKeyStroke('S',InputEvent.CTRL_MASK)));
  272.         menufile.add(menuItem(translation.getProperty("Save_As"),KeyEvent.VK_A));
  273.         JMenu menuexport=new JMenu(translation.getProperty("Export"));
  274.         menuexport.setMnemonic(KeyEvent.VK_X);
  275.         menuexport.add(menuItem(translation.getProperty("as_MDL_MOL"),KeyEvent.VK_M,null,KeyStroke.getKeyStroke('M',InputEvent.CTRL_MASK+InputEvent.SHIFT_MASK)));
  276.         menuexport.add(menuItem(translation.getProperty("as_CML_XML"),KeyEvent.VK_X,null,KeyStroke.getKeyStroke('X',InputEvent.CTRL_MASK+InputEvent.SHIFT_MASK)));
  277.         menuexport.add(menuItem(translation.getProperty("as_SVG"),KeyEvent.VK_S,null,KeyStroke.getKeyStroke('S',InputEvent.CTRL_MASK+InputEvent.SHIFT_MASK)));
  278.         menufile.add(menuexport);
  279.  
  280.         menufile.addSeparator();
  281.         if (streamMode) menufile.add(menuItem(translation.getProperty("Save_and_Quit"),KeyEvent.VK_Q,null,KeyStroke.getKeyStroke('Q',InputEvent.CTRL_MASK)));
  282.         else if (slaveMode) menufile.add(menuItem(translation.getProperty("Close"),KeyEvent.VK_C,null,KeyStroke.getKeyStroke('W',InputEvent.CTRL_MASK)));
  283.         else menufile.add(menuItem(translation.getProperty("Quit"),KeyEvent.VK_Q,null,KeyStroke.getKeyStroke('Q',InputEvent.CTRL_MASK)));
  284.        
  285.         JMenu menuedit=new JMenu(translation.getProperty("Edit"));
  286.         menuedit.setMnemonic(KeyEvent.VK_E);
  287.         menuedit.add(menuItem(translation.getProperty("Editttt"),KeyEvent.VK_E,toolIcons[TOOL_DIALOG],KeyStroke.getKeyStroke(' ',InputEvent.CTRL_MASK)));
  288.         menuedit.add(menuItem(translation.getProperty("Undo"),KeyEvent.VK_U,toolIcons[TOOL_UNDO],KeyStroke.getKeyStroke('Z',InputEvent.CTRL_MASK)));
  289.         menuedit.add(menuItem(translation.getProperty("Redo"),KeyEvent.VK_R,toolIcons[TOOL_REDO],
  290.                                                         KeyStroke.getKeyStroke('Z',InputEvent.CTRL_MASK+InputEvent.SHIFT_MASK)));
  291.    
  292.    
  293.         menuedit.add(menuItem(translation.getProperty("Cut"),KeyEvent.VK_X,toolIcons[TOOL_CUT],KeyStroke.getKeyStroke('X',InputEvent.CTRL_MASK)));
  294.         menuedit.add(menuItem(translation.getProperty("Copy"),KeyEvent.VK_C,toolIcons[TOOL_COPY],KeyStroke.getKeyStroke('C',InputEvent.CTRL_MASK)));
  295.         menuedit.add(menuItem(translation.getProperty("Copy_SVG"),KeyEvent.VK_V,null,KeyStroke.getKeyStroke('C',InputEvent.CTRL_MASK+InputEvent.SHIFT_MASK)));
  296.         menuedit.add(menuItem(translation.getProperty("Paste"),KeyEvent.VK_V,toolIcons[TOOL_PASTE],KeyStroke.getKeyStroke('V',InputEvent.CTRL_MASK)));
  297.         menuedit.addSeparator();
  298.         menuedit.add(menuItem(translation.getProperty("Select_All"),KeyEvent.VK_S,null,KeyStroke.getKeyStroke('A',InputEvent.CTRL_MASK)));
  299.         menuedit.add(menuItem(translation.getProperty("Next_Atom"),KeyEvent.VK_N,null,KeyStroke.getKeyStroke('E',InputEvent.CTRL_MASK)));
  300.         menuedit.add(menuItem(translation.getProperty("Previous_Atom"),KeyEvent.VK_P,null,KeyStroke.getKeyStroke('E',InputEvent.CTRL_MASK+InputEvent.SHIFT_MASK)));
  301.         menuedit.add(menuItem(translation.getProperty("Next_Group"),KeyEvent.VK_G,null,KeyStroke.getKeyStroke('G',InputEvent.CTRL_MASK)));
  302.         menuedit.add(menuItem(translation.getProperty("Previous_Group"),KeyEvent.VK_R,null,KeyStroke.getKeyStroke('G',InputEvent.CTRL_MASK+InputEvent.SHIFT_MASK)));
  303.         menuedit.addSeparator();
  304.         menuedit.add(menuItem(translation.getProperty("Flip_Horizontal"),KeyEvent.VK_H,null,null));
  305.         menuedit.add(menuItem(translation.getProperty("Flip_Vertical"),KeyEvent.VK_V,null,null));
  306.         menuedit.add(menuItem(translation.getProperty("Rotate_P45"),KeyEvent.VK_4,null,null));
  307.         menuedit.add(menuItem(translation.getProperty("Rotate_M45"),KeyEvent.VK_5,null,null));
  308.         menuedit.add(menuItem(translation.getProperty("Rotate_P90"),KeyEvent.VK_9,null,null));
  309.         menuedit.add(menuItem(translation.getProperty("Rotate_M90"),KeyEvent.VK_0,null,null));
  310.         menuedit.addSeparator();
  311.         menuedit.add(menuItem(translation.getProperty("Add_Temporary_Template"),KeyEvent.VK_T,null,null));
  312.         menuedit.add(menuItem(translation.getProperty("Normalise_Bond_Lengths"),KeyEvent.VK_N,null,null));
  313.        
  314.         JMenu menuview=new JMenu(translation.getProperty("View"));
  315.         menuview.setMnemonic(KeyEvent.VK_V);
  316.         menuview.add(menuItem(translation.getProperty("Zoom_Full"),KeyEvent.VK_F,null,KeyStroke.getKeyStroke('0',InputEvent.CTRL_MASK)));
  317.         menuview.add(menuItem(translation.getProperty("Zoom_In"),KeyEvent.VK_I,null,KeyStroke.getKeyStroke('=',InputEvent.CTRL_MASK)));
  318.         menuview.add(menuItem(translation.getProperty("Zoom_Out"),KeyEvent.VK_O,null,KeyStroke.getKeyStroke('-',InputEvent.CTRL_MASK)));
  319.         menuview.addSeparator();
  320.         ButtonGroup showBG=new ButtonGroup();
  321.         menuview.add(radioMenuItem(translation.getProperty("Show_Elements"),KeyEvent.VK_E,true,showBG));
  322.         menuview.add(radioMenuItem(translation.getProperty("Show_All_Elements"),KeyEvent.VK_A,false,showBG));
  323.         menuview.add(radioMenuItem(translation.getProperty("Show_Indices"),KeyEvent.VK_I,false,showBG));
  324.         menuview.add(radioMenuItem(translation.getProperty("Show_Ring_ID"),KeyEvent.VK_R,false,showBG));
  325.         menuview.add(radioMenuItem(translation.getProperty("Show_CIP_Priority"),KeyEvent.VK_C,false,showBG));
  326.         menuview.add(radioMenuItem(translation.getProperty("Show_Mapping_Number"),KeyEvent.VK_M,false,showBG));
  327.        
  328.         JMenu menutool=new JMenu(translation.getProperty("Tool"));
  329.         menutool.setMnemonic(KeyEvent.VK_T);
  330.         menutool.add(menuItem(translation.getProperty("Cursor"),KeyEvent.VK_C,toolIcons[TOOL_CURSOR],KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE,0)));
  331.         menutool.add(menuItem(translation.getProperty("Rotator"),KeyEvent.VK_R,toolIcons[TOOL_ROTATOR],KeyStroke.getKeyStroke('R',InputEvent.CTRL_MASK)));
  332.         menutool.add(menuItem(translation.getProperty("Erasor"),KeyEvent.VK_E,toolIcons[TOOL_ERASOR],KeyStroke.getKeyStroke('D',InputEvent.CTRL_MASK)));
  333.         menutool.add(menuItem(translation.getProperty("Edit_Atom"),KeyEvent.VK_A,toolIcons[TOOL_EDIT],KeyStroke.getKeyStroke(',',InputEvent.CTRL_MASK)));
  334.         menutool.add(menuItem(translation.getProperty("Set_Atom"),KeyEvent.VK_S,new ImageIcon(getClass().getResource("/images/ASelMenu.png")),
  335.                                                                                 KeyStroke.getKeyStroke('.',InputEvent.CTRL_MASK)));
  336.         menutool.add(menuItem(translation.getProperty("Single_Bond"),KeyEvent.VK_1,toolIcons[TOOL_SINGLE],KeyStroke.getKeyStroke('1',InputEvent.CTRL_MASK)));
  337.         menutool.add(menuItem(translation.getProperty("Double_Bond"),KeyEvent.VK_2,toolIcons[TOOL_DOUBLE],KeyStroke.getKeyStroke('2',InputEvent.CTRL_MASK)));
  338.         menutool.add(menuItem(translation.getProperty("Triple_Bond"),KeyEvent.VK_3,toolIcons[TOOL_TRIPLE],KeyStroke.getKeyStroke('3',InputEvent.CTRL_MASK)));
  339.         menutool.add(menuItem(translation.getProperty("Zero_Bond"),KeyEvent.VK_0,toolIcons[TOOL_ZERO],KeyStroke.getKeyStroke('0',InputEvent.CTRL_MASK)));
  340.         menutool.add(menuItem(translation.getProperty("Inclined_Bond"),KeyEvent.VK_I,toolIcons[TOOL_INCLINED]));
  341.         menutool.add(menuItem(translation.getProperty("Declined_Bond"),KeyEvent.VK_D,toolIcons[TOOL_DECLINED]));
  342.         menutool.add(menuItem(translation.getProperty("Unknown_Bond"),KeyEvent.VK_U,toolIcons[TOOL_UNKNOWN]));
  343.         menutool.add(menuItem(translation.getProperty("Charge"),KeyEvent.VK_H,toolIcons[TOOL_CHARGE],KeyStroke.getKeyStroke('H',InputEvent.CTRL_MASK)));
  344.         menutool.add(menuItem(translation.getProperty("Template_Tool"),KeyEvent.VK_T,toolIcons[TOOL_TEMPLATE],KeyStroke.getKeyStroke('T',InputEvent.CTRL_MASK)));
  345.         menutool.add(menuItem(translation.getProperty("Select_Template"),KeyEvent.VK_T,toolIcons[TOOL_TEMPLATE],
  346.                                                         KeyStroke.getKeyStroke('T',InputEvent.CTRL_MASK+InputEvent.SHIFT_MASK)));
  347.         JMenu menuhydr=new JMenu(translation.getProperty("Hydrogen"));
  348.         menuhydr.setMnemonic(KeyEvent.VK_Y);
  349.         chkShowHydr=new JCheckBoxMenuItem(translation.getProperty("Show_Hydrogen"));
  350.         chkShowHydr.setMnemonic(KeyEvent.VK_Y);
  351.         chkShowHydr.setSelected(true);
  352.         chkShowHydr.addActionListener(this);
  353.         menuhydr.add(chkShowHydr);
  354.         menuhydr.add(menuItem(translation.getProperty("Set_Explicit"),KeyEvent.VK_E));
  355.         menuhydr.add(menuItem(translation.getProperty("Clear_Explicit"),KeyEvent.VK_X));
  356.         menuhydr.add(menuItem(translation.getProperty("Zero_Explicit"),KeyEvent.VK_Z));
  357.         menuhydr.add(menuItem(translation.getProperty("Create_Actual"),KeyEvent.VK_C));
  358.         menuhydr.add(menuItem(translation.getProperty("Delete_Actual"),KeyEvent.VK_D));
  359.  
  360.         JMenu menuster=new JMenu(translation.getProperty("Stereochemistry"));
  361.         menuster.setMnemonic(KeyEvent.VK_S);
  362.         chkShowSter=new JCheckBoxMenuItem(translation.getProperty("Show_Stereolabels"));
  363.         chkShowSter.setMnemonic(KeyEvent.VK_L);
  364.         chkShowSter.setSelected(false);
  365.         chkShowSter.addActionListener(this);
  366.         menuster.add(chkShowSter);
  367.         menuster.add(menuItem(translation.getProperty("Invert_Stereochemistry"),KeyEvent.VK_I));
  368.         menuster.add(menuItem(translation.getProperty("Set_R/Z"),KeyEvent.VK_R));
  369.         menuster.add(menuItem(translation.getProperty("Set_S/E"),KeyEvent.VK_S));
  370.         menuster.add(menuItem(translation.getProperty("Cycle_Wedges"),KeyEvent.VK_C));
  371.         menuster.add(menuItem(translation.getProperty("Remove_Wedges"),KeyEvent.VK_W));
  372.  
  373.         JMenu menuhelp=new JMenu(translation.getProperty("Help"));
  374.         menuhelp.setMnemonic(KeyEvent.VK_H);
  375.         menuhelp.add(menuItem(translation.getProperty("About"),KeyEvent.VK_A));
  376.  
  377.         menubar.add(menufile);
  378.         menubar.add(menuedit);
  379.         menubar.add(menuview);
  380.         menubar.add(menutool);
  381.         menubar.add(menuhydr);
  382.         menubar.add(menuster);
  383.         menubar.add(Box.createHorizontalGlue());
  384.         menubar.add(menuhelp);
  385.  
  386.         return menubar;
  387.     }    
  388.    
  389.     // builds and returns a menu bar suitable for the applet-style invocation
  390.     private JMenuBar menuBarApplet()
  391.     {
  392.         JMenuBar menubar=new JMenuBar();
  393.         AppletMenu menublock=new AppletMenu(translation.getProperty("Block"));
  394.         AppletMenu menuselect=new AppletMenu(translation.getProperty("Select"));
  395.         AppletMenu menutransform=new AppletMenu(translation.getProperty("Transform"));
  396.         AppletMenu menuzoom=new AppletMenu(translation.getProperty("Zoom"));
  397.         AppletMenu menushow=new AppletMenu(translation.getProperty("Show"));
  398.         AppletMenu menuhydrogen=new AppletMenu(translation.getProperty("Hydrogen"));
  399.         AppletMenu menuhelp=new AppletMenu(translation.getProperty("Help"));
  400.         if( MENU_SELECTION[0]){
  401.          menublock.setMnemonic(KeyEvent.VK_B);
  402.          menublock.add(menuItem(translation.getProperty("New"),KeyEvent.VK_N,null,KeyStroke.getKeyStroke('N',InputEvent.CTRL_MASK)));
  403.          menublock.add(menuItem(translation.getProperty("Editttt"),KeyEvent.VK_E,null,KeyStroke.getKeyStroke(' ',InputEvent.CTRL_MASK)));
  404.          menublock.add(menuItem(translation.getProperty("Undo"),KeyEvent.VK_U,null,KeyStroke.getKeyStroke('Z',InputEvent.CTRL_MASK)));
  405.          menublock.add(menuItem(translation.getProperty("Redo"),KeyEvent.VK_R,null,KeyStroke.getKeyStroke('Z',InputEvent.CTRL_MASK+InputEvent.SHIFT_MASK)));
  406.          menublock.add(menuItem(translation.getProperty("Cut"),KeyEvent.VK_X,null,KeyStroke.getKeyStroke('X',InputEvent.CTRL_MASK)));
  407.          menublock.add(menuItem(translation.getProperty("Copy"),KeyEvent.VK_C,null,KeyStroke.getKeyStroke('C',InputEvent.CTRL_MASK)));
  408.          menublock.add(menuItem(translation.getProperty("Paste"),KeyEvent.VK_V,null,KeyStroke.getKeyStroke('V',InputEvent.CTRL_MASK)));
  409.         menubar.add(menublock);
  410.         }
  411.         if( MENU_SELECTION[1]){
  412.         menuselect.setMnemonic(KeyEvent.VK_S);
  413.         menuselect.add(menuItem(translation.getProperty("Select_All"),KeyEvent.VK_S,null,KeyStroke.getKeyStroke('A',InputEvent.CTRL_MASK)));
  414.         menuselect.add(menuItem(translation.getProperty("Next_Atom"),KeyEvent.VK_N,null,KeyStroke.getKeyStroke('E',InputEvent.CTRL_MASK)));
  415.         menuselect.add(menuItem(translation.getProperty("Previous_Atom"),KeyEvent.VK_P,null,KeyStroke.getKeyStroke('E',InputEvent.CTRL_MASK+InputEvent.SHIFT_MASK)));
  416.         menuselect.add(menuItem(translation.getProperty("Next_Group"),KeyEvent.VK_G,null,KeyStroke.getKeyStroke('G',InputEvent.CTRL_MASK)));
  417.         menuselect.add(menuItem(translation.getProperty("Previous_Group"),KeyEvent.VK_R,null,KeyStroke.getKeyStroke('G',InputEvent.CTRL_MASK+InputEvent.SHIFT_MASK)));
  418.         menubar.add(menuselect);       
  419.         }
  420.  
  421.         if( MENU_SELECTION[2]){
  422.         menutransform.setMnemonic(KeyEvent.VK_T);
  423.         menutransform.add(menuItem(translation.getProperty("Flip_Horizontal"),KeyEvent.VK_H,null,null));
  424.         menutransform.add(menuItem(translation.getProperty("Flip_Vertical"),KeyEvent.VK_V,null,null));
  425.         menutransform.add(menuItem(translation.getProperty("Rotate_P45"),KeyEvent.VK_4,null,null));
  426.         menutransform.add(menuItem(translation.getProperty("Rotate_M45"),KeyEvent.VK_5,null,null));
  427.         menutransform.add(menuItem(translation.getProperty("Rotate_P90"),KeyEvent.VK_9,null,null));
  428.         menutransform.add(menuItem(translation.getProperty("Rotate_M90"),KeyEvent.VK_0,null,null));
  429.         menutransform.addSeparator();
  430.         menutransform.add(menuItem(translation.getProperty("Add_Temporary_Template"),KeyEvent.VK_T,null,null));
  431.         menutransform.add(menuItem(translation.getProperty("Normalise_Bond_Lengths"),KeyEvent.VK_N,null,null));
  432.         menubar.add(menutransform);
  433.         }
  434.  
  435.         if( MENU_SELECTION[3]){
  436.         menuzoom.setMnemonic(KeyEvent.VK_Z);
  437.         menuzoom.add(menuItem(translation.getProperty("Zoom_Full"),KeyEvent.VK_F,null,KeyStroke.getKeyStroke('0',InputEvent.CTRL_MASK)));
  438.         menuzoom.add(menuItem(translation.getProperty("Zoom_In"),KeyEvent.VK_I,null,KeyStroke.getKeyStroke('=',InputEvent.CTRL_MASK)));
  439.         menuzoom.add(menuItem(translation.getProperty("Zoom_Out"),KeyEvent.VK_O,null,KeyStroke.getKeyStroke('-',InputEvent.CTRL_MASK)));
  440.         menubar.add(menuzoom);
  441.         }
  442.  
  443.         if( MENU_SELECTION[4]){
  444.         menushow.setMnemonic(KeyEvent.VK_O);
  445.         ButtonGroup showBG=new ButtonGroup();
  446.         menushow.add(radioMenuItem(translation.getProperty("Show_Elements"),KeyEvent.VK_E,true,showBG));
  447.         menushow.add(radioMenuItem(translation.getProperty("Show_All_Elements"),KeyEvent.VK_A,false,showBG));
  448.         menushow.add(radioMenuItem(translation.getProperty("Show_Indices"),KeyEvent.VK_I,false,showBG));
  449.         menushow.add(radioMenuItem(translation.getProperty("Show_Ring_ID"),KeyEvent.VK_R,false,showBG));
  450.         menushow.add(radioMenuItem(translation.getProperty("Show_CIP_Priority"),KeyEvent.VK_C,false,showBG));
  451.         menushow.add(radioMenuItem(translation.getProperty("Show_Mapping_Number"),KeyEvent.VK_M,false,showBG));
  452.         menubar.add(menushow);
  453.         }
  454.  
  455.         if( MENU_SELECTION[5]){
  456.         menuhydrogen.setMnemonic(KeyEvent.VK_H);
  457.         chkShowHydr=new JCheckBoxMenuItem(translation.getProperty("Show_Hydrogen"));
  458.         chkShowHydr.setMnemonic(KeyEvent.VK_Y);
  459.         chkShowHydr.setSelected(true);
  460.         chkShowHydr.addActionListener(this);
  461.         menuhydrogen.add(chkShowHydr);
  462.         menuhydrogen.add(menuItem(translation.getProperty("Set_Explicit"),KeyEvent.VK_E));
  463.         menuhydrogen.add(menuItem(translation.getProperty("Clear_Explicit"),KeyEvent.VK_X));
  464.         menuhydrogen.add(menuItem(translation.getProperty("Zero_Explicit"),KeyEvent.VK_Z));
  465.         menuhydrogen.add(menuItem(translation.getProperty("Create_Actual"),KeyEvent.VK_C));
  466.         menuhydrogen.add(menuItem(translation.getProperty("Delete_Actual"),KeyEvent.VK_D));
  467.         menubar.add(menuhydrogen);
  468.         }
  469.  
  470.         if( MENU_SELECTION[6]){
  471.         AppletMenu menustereo=new AppletMenu(translation.getProperty("Stereo"));
  472.         menustereo.setMnemonic(KeyEvent.VK_E);
  473.         chkShowSter=new JCheckBoxMenuItem(translation.getProperty("Show_Stereolabels"));
  474.         chkShowSter.setMnemonic(KeyEvent.VK_L);
  475.         chkShowSter.setSelected(false);
  476.         chkShowSter.addActionListener(this);
  477.         menustereo.add(chkShowSter);
  478.         menustereo.add(menuItem(translation.getProperty("Invert_Stereochemistry"),KeyEvent.VK_I));
  479.         menustereo.add(menuItem(translation.getProperty("Set R/Z"),KeyEvent.VK_R));
  480.         menustereo.add(menuItem(translation.getProperty("Set_S/E"),KeyEvent.VK_S));
  481.         menustereo.add(menuItem(translation.getProperty("Cycle_Wedges"),KeyEvent.VK_C));
  482.         menustereo.add(menuItem(translation.getProperty("Remove_Wedges"),KeyEvent.VK_W));
  483.         menubar.add(menustereo);
  484.         }
  485.  
  486.         if( MENU_SELECTION[7]){
  487.         menuhelp.setMnemonic(KeyEvent.VK_P);
  488.         menuhelp.add(menuItem(translation.getProperty("About"),KeyEvent.VK_A));
  489.         menubar.add(menuhelp); 
  490.         }
  491.        
  492.         return menubar;
  493.     }
  494.    
  495.     public Molecule molData() {return editor.molData();} // shallow copy, use with care
  496.     public void setMolecule(Molecule Mol)
  497.     {
  498.         editor.replace(Mol);
  499.         editor.RotateMolecule();
  500.         editor.scaleToFit();
  501.         editor.notifySaved();
  502.     }
  503.     public void addMolecule(Molecule Mol)
  504.     {
  505.         editor.addArbitraryFragment(Mol);
  506.         editor.scaleToFit();
  507.         editor.notifySaved();
  508.     }
  509.     public void scaleToFit() {editor.scaleToFit();}
  510.    
  511.     JMenuItem menuItem(String txt,int key) {return menuItem(txt,key,null,null);}
  512.     JMenuItem menuItem(String txt,int key,Icon icon) {return menuItem(txt,key,icon,null);}
  513.     JMenuItem menuItem(String txt,int key,Icon icon,KeyStroke accel)
  514.     {
  515.         JMenuItem mi=new JMenuItem(txt,key);
  516.         mi.addActionListener(this);
  517.         if (icon!=null) mi.setIcon(icon);
  518.         if (accel!=null) mi.setAccelerator(accel);
  519.         return mi;
  520.     }
  521.     JRadioButtonMenuItem radioMenuItem(String txt,int key,boolean sel,ButtonGroup bg)
  522.     {
  523.         JRadioButtonMenuItem mi=new JRadioButtonMenuItem(txt,sel);
  524.         mi.addActionListener(this);
  525.         mi.setMnemonic(key);
  526.         bg.add(mi);
  527.         return mi;
  528.     }
  529.    
  530.     void fileQuit()
  531.     {
  532.         if (!streamMode)
  533.         {
  534.             if (editor.isDirty())
  535.             {
  536.                 if (JOptionPane.showConfirmDialog(null,
  537.                     "Current structure has been modified. Exit without saving?","Quit",
  538.                     JOptionPane.YES_NO_OPTION)!=JOptionPane.YES_OPTION) return;
  539.             }
  540.         }
  541.         else
  542.         {
  543.             writeStream();
  544.         }
  545.  
  546.         if (frameParent!=null) frameParent.dispose();
  547.  
  548.         return;
  549.     }
  550.     void fileNew()
  551.     {
  552.         if (editor.molData().numAtoms()>0)
  553.         {
  554.             if (JOptionPane.showConfirmDialog(null,
  555.                 "Clear current structure and start anew?","New",
  556.                 JOptionPane.YES_NO_OPTION)!=JOptionPane.YES_OPTION) return;
  557.         }
  558.         editor.clear();
  559.         filename=null;
  560.         if (frameParent!=null && saver==null) frameParent.setTitle("WIMSchem");
  561.         editor.notifySaved();
  562.     }
  563.     void fileNewWindow()
  564.     {
  565.         MainWindow mw=new MainWindow(null,false);
  566.         mw.setVisible(true);
  567.     }
  568.     void fileNewDataSheet()
  569.     {
  570.         DataWindow dw=new DataWindow(null);
  571.         dw.setVisible(true);
  572.     }
  573.     void fileOpen()
  574.     {
  575.         JFileChooser chooser=new JFileChooser(System.getenv().get("PWD"));
  576.         chooser.setDragEnabled(false);
  577.         chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
  578.         chooser.setFileFilter(new FileExtFilter("Molecular Structures",".el;.mol;.sdf;.xml"));
  579.         chooser.setAccessory(new FileMolPreview(chooser));
  580.         if (chooser.showOpenDialog(frameParent)!=JFileChooser.APPROVE_OPTION) return;
  581.        
  582.         boolean fresh=editor.isEmpty();
  583.         String newfn=chooser.getSelectedFile().getPath();
  584.         boolean anything=editor.molData().numAtoms()>0;
  585.         try
  586.         {
  587.             FileInputStream istr=new FileInputStream(newfn);
  588.             if (!DataWindow.ALLOW && MoleculeStream.examineIsDatabase(istr))
  589.             {   // !! this section is to be deprecated when DataSheet is fully functional
  590.                 istr.close();
  591.                 CatalogWindow cw=new CatalogWindow(newfn);
  592.                 cw.setVisible(true);
  593.             }
  594.             else if (DataSheetStream.examineIsXMLDS(istr) || DataSheetStream.examineIsMDLSDF(istr))
  595.             {
  596.                 istr.close();
  597.                 DataWindow dw=new DataWindow(newfn);
  598.                 dw.setVisible(true);
  599.             }
  600.             else
  601.             {
  602.                 Molecule frag=MoleculeStream.readUnknown(istr);
  603.                 editor.addArbitraryFragment(frag);
  604.                 istr.close();
  605.                 if (fresh) setFilename(newfn);
  606.                 if (!anything) editor.notifySaved();
  607.             }
  608.         }
  609.         catch (IOException e)
  610.         {
  611.             JOptionPane.showMessageDialog(null,e.toString(),"Open Failed",JOptionPane.ERROR_MESSAGE);
  612.             //e.printStackTrace();
  613.             return;
  614.         }
  615.     }
  616.    
  617.     void fileSave()
  618.     {
  619.         if (filename==null && saver==null) {fileSaveAs(); return;}
  620.         saveCurrent();
  621.     }
  622.    
  623.     void fileSaveAs()
  624.     {
  625.         JFileChooser chooser=new JFileChooser(System.getenv().get("PWD"));
  626.         chooser.setDragEnabled(false);
  627.         chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
  628.         chooser.setFileFilter(new FileExtFilter("WIMSchem Files",".el"));
  629.         chooser.setAccessory(new FileMolPreview(chooser));
  630.         if (chooser.showSaveDialog(frameParent)!=JFileChooser.APPROVE_OPTION) return;
  631.    
  632.         String fn=chooser.getSelectedFile().getPath();
  633.         if (chooser.getSelectedFile().getName().indexOf('.')<0) fn=fn+".el";
  634.    
  635.         File newf=new File(fn);
  636.         if (newf.exists())
  637.         {
  638.             if (JOptionPane.showConfirmDialog(null,
  639.                 "Overwrite existing file ["+newf.getName()+"]?","Save As",
  640.                 JOptionPane.YES_NO_OPTION)!=JOptionPane.YES_OPTION) return;
  641.         }      
  642.    
  643.         setFilename(fn);
  644.         saveCurrent(true);
  645.     }
  646.    
  647.     void fileExportMDLMOL()
  648.     {
  649.         JFileChooser chooser=new JFileChooser(System.getenv().get("PWD"));
  650.         chooser.setDragEnabled(false);
  651.         chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
  652.         chooser.setFileFilter(new FileExtFilter("MDL MOL Files",".mol"));
  653.         chooser.setAccessory(new FileMolPreview(chooser));
  654.         if (chooser.showSaveDialog(frameParent)!=JFileChooser.APPROVE_OPTION) return;
  655.  
  656.         String fn=chooser.getSelectedFile().getPath();
  657.         if (chooser.getSelectedFile().getName().indexOf('.')<0) fn=fn+".mol";
  658.  
  659.         File newf=new File(fn);
  660.         if (newf.exists())
  661.         {
  662.             if (JOptionPane.showConfirmDialog(null,
  663.                 "Overwrite existing file ["+newf.getName()+"]?","Export MDL MOL",
  664.                 JOptionPane.YES_NO_OPTION)!=JOptionPane.YES_OPTION) return;
  665.         }      
  666.  
  667.         try
  668.         {
  669.             FileOutputStream ostr=new FileOutputStream(fn);
  670.             MoleculeStream.writeMDLMOL(ostr,editor.molData());
  671.             ostr.close();
  672.         }
  673.         catch (IOException e)
  674.         {
  675.             JOptionPane.showMessageDialog(null,e.toString(),"Export Failed",JOptionPane.ERROR_MESSAGE);
  676.         }
  677.     }
  678.    
  679.     void fileExportSVG()
  680.     {
  681.         JFileChooser chooser=new JFileChooser(System.getenv().get("PWD"));
  682.         chooser.setDragEnabled(false);
  683.         chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
  684.         chooser.setFileFilter(new FileExtFilter("SVG Files",".svg"));
  685.         chooser.setAccessory(new FileMolPreview(chooser));
  686.         if (chooser.showSaveDialog(frameParent)!=JFileChooser.APPROVE_OPTION) return;
  687.  
  688.         String fn=chooser.getSelectedFile().getPath();
  689.         if (chooser.getSelectedFile().getName().indexOf('.')<0) fn=fn+".svg";
  690.  
  691.         File newf=new File(fn);
  692.         if (newf.exists())
  693.         {
  694.             if (JOptionPane.showConfirmDialog(null,
  695.                 "Overwrite existing file ["+newf.getName()+"]?","Export SVG",
  696.                 JOptionPane.YES_NO_OPTION)!=JOptionPane.YES_OPTION) return;
  697.         }      
  698.  
  699.         try
  700.         {
  701.             FileOutputStream ostr=new FileOutputStream(fn);
  702.             SVGMolecule svgmol=new SVGMolecule(editor.molData());
  703.             svgmol.draw();
  704.             svgmol.build(new PrintWriter(ostr));
  705.             ostr.close();
  706.         }
  707.         catch (IOException e)
  708.         {
  709.             JOptionPane.showMessageDialog(null,e.toString(),"Export Failed",JOptionPane.ERROR_MESSAGE);
  710.         }
  711.     }
  712.    
  713.     void fileExportCMLXML()
  714.     {
  715.         JFileChooser chooser=new JFileChooser(System.getenv().get("PWD"));
  716.         chooser.setDragEnabled(false);
  717.         chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
  718.         chooser.setFileFilter(new FileExtFilter("XML Files",".xml"));
  719.         chooser.setAccessory(new FileMolPreview(chooser));
  720.         if (chooser.showSaveDialog(frameParent)!=JFileChooser.APPROVE_OPTION) return;
  721.  
  722.         String fn=chooser.getSelectedFile().getPath();
  723.         if (chooser.getSelectedFile().getName().indexOf('.')<0) fn=fn+".xml";
  724.  
  725.         File newf=new File(fn);
  726.         if (newf.exists())
  727.         {
  728.             if (JOptionPane.showConfirmDialog(null,
  729.                 "Overwrite existing file ["+newf.getName()+"]?","Export CML XML",
  730.                 JOptionPane.YES_NO_OPTION)!=JOptionPane.YES_OPTION) return;
  731.         }      
  732.  
  733.         try
  734.         {
  735.             FileOutputStream ostr=new FileOutputStream(fn);
  736.             MoleculeStream.writeCMLXML(ostr,editor.molData());
  737.             ostr.close();
  738.         }
  739.         catch (IOException e)
  740.         {
  741.             JOptionPane.showMessageDialog(null,e.toString(),"Export Failed",JOptionPane.ERROR_MESSAGE);
  742.         }
  743.     }
  744.  
  745.     void setFilename(String fn)
  746.     {
  747.         if (fn.length()==0) {filename=null; return;}
  748.         filename=fn;
  749.        
  750.         if (!streamMode)
  751.         {
  752.            String chopfn=fn;
  753.            int i=chopfn.lastIndexOf("/");
  754.            if (i>=0) chopfn=chopfn.substring(i+1);
  755.            if (frameParent!=null && saver==null) frameParent.setTitle(chopfn+" - WIMSchem");
  756.         }
  757.         else {if (frameParent!=null && saver==null) frameParent.setTitle("WIMSchem");}
  758.     }
  759.    
  760.     void saveCurrent() {saveCurrent(false);}
  761.     void saveCurrent(boolean force)
  762.     {
  763.         if (saver!=null && !force)
  764.         {
  765.             saver.saveMolecule(editor.molData().clone());
  766.             editor.notifySaved();
  767.             return;
  768.         }
  769.    
  770.         try
  771.         {
  772.             boolean fmtNative=true;
  773.        
  774.             if (filename.toLowerCase().endsWith(".mol"))
  775.             {
  776.                 String msg="The filename to save ends with '.mol', which is the\n"+
  777.                            "conventional suffix for MDL MOL-files. Exporting to\n"+
  778.                            "this format will cause some information loss. Do you wish\n"+
  779.                            "to save in MDL MOL-file format?";
  780.                 if (JOptionPane.showConfirmDialog(null,msg,"Format",JOptionPane.YES_NO_OPTION)==JOptionPane.YES_OPTION)
  781.                     fmtNative=false;
  782.             }
  783.        
  784.             FileOutputStream ostr=new FileOutputStream(filename);
  785.             if (fmtNative) MoleculeStream.writeNative(ostr,editor.molData());
  786.             else MoleculeStream.writeMDLMOL(ostr,editor.molData());
  787.             ostr.close();
  788.             editor.notifySaved();
  789.         }
  790.         catch (IOException e)
  791.         {
  792.             JOptionPane.showMessageDialog(null,e.toString(),"Save Failed",JOptionPane.ERROR_MESSAGE);
  793.         }
  794.     }
  795.    
  796.     void readStream()
  797.     {
  798.         try
  799.         {
  800.             Molecule frag=MoleculeStream.readUnknown(System.in);
  801.             editor.addArbitraryFragment(frag);
  802.         }
  803.         catch (IOException e)
  804.         {
  805.             JOptionPane.showMessageDialog(null,e.toString(),"<stdin> Read Failed",JOptionPane.ERROR_MESSAGE);
  806.             return;
  807.         }
  808.     }
  809.     void writeStream()
  810.     {
  811.         Molecule mol=editor.molData();
  812.         try
  813.         {
  814.             MoleculeStream.writeMDLMOL(System.out,mol);
  815.             MoleculeStream.writeNative(System.out,mol);
  816.         }
  817.         catch (IOException e)
  818.         {
  819.             JOptionPane.showMessageDialog(null,e.toString(),"<stdout> Write Failed",JOptionPane.ERROR_MESSAGE);
  820.         }
  821.     }
  822.    
  823.     void testMol()
  824.     {
  825.         Molecule mol=new Molecule();
  826.        
  827.         mol.addAtom("N",0,0);
  828.         mol.addAtom("C",1.2,0);
  829.         mol.addAtom("O",2,0.8);
  830.         mol.addAtom("H",3,-0.8);
  831.         mol.addAtom("H",4,0);
  832.         mol.addBond(1,2,1);
  833.         mol.addBond(2,3,2);
  834.         mol.addBond(3,4,1);
  835.         mol.addBond(4,5,0);
  836.        
  837.         editor.replace(mol);
  838.     }
  839.    
  840.     void editCut()
  841.     {
  842.         Molecule frag=editor.selectedSubgraph();
  843.         try
  844.         {
  845.             StringWriter sw=new StringWriter();
  846.             BufferedWriter bw=new BufferedWriter(sw);
  847.             MoleculeStream.writeMDLMOL(bw,frag);
  848.             MoleculeStream.writeNative(bw,frag);
  849.             if (useLocalClipboard)
  850.             {
  851.                 appletClipboard=sw.toString();
  852.             }
  853.             else
  854.             {
  855.                 Clipboard clip=Toolkit.getDefaultToolkit().getSystemClipboard();
  856.                 clip.setContents(new StringSelection(sw.toString()),this);
  857.             }
  858.             editor.deleteSelected(); // (keep this within the exception trap)
  859.         }
  860.         catch (IOException e)
  861.         {
  862.             JOptionPane.showMessageDialog(null,e.toString(),"Cut Failed",JOptionPane.ERROR_MESSAGE);
  863.         }
  864.     }
  865.    
  866.     void editCopy()
  867.     {
  868.         Molecule frag=editor.selectedSubgraph();
  869.         try
  870.         {
  871.             StringWriter sw=new StringWriter();
  872.             BufferedWriter bw=new BufferedWriter(sw);
  873.             MoleculeStream.writeMDLMOL(bw,frag);
  874.             MoleculeStream.writeNative(bw,frag);
  875.             if (useLocalClipboard)
  876.             {
  877.                 appletClipboard=sw.toString();
  878.             }
  879.             else
  880.             {
  881.                 Clipboard clip=Toolkit.getDefaultToolkit().getSystemClipboard();
  882.                 clip.setContents(new StringSelection(sw.toString()),this);
  883.             }
  884.         }
  885.         catch (IOException e)
  886.         {
  887.             JOptionPane.showMessageDialog(null,e.toString(),"Copy Failed",JOptionPane.ERROR_MESSAGE);
  888.         }
  889.     }
  890.  
  891.     void editCopySVG()
  892.     {
  893.         StringWriter sw=new StringWriter();
  894.         SVGMolecule svgmol=new SVGMolecule(editor.molData());
  895.         svgmol.draw();
  896.         svgmol.build(new PrintWriter(sw));
  897.         if (useLocalClipboard)
  898.         {
  899.             appletClipboard=sw.toString();
  900.         }
  901.         else
  902.         {
  903.             Clipboard clip=Toolkit.getDefaultToolkit().getSystemClipboard();
  904.             clip.setContents(new StringSelection(sw.toString()),this);
  905.         }
  906.     }
  907.    
  908.     void editPaste()
  909.     {
  910.         try
  911.         {
  912.             String cliptext=null;
  913.             if (useLocalClipboard) cliptext=appletClipboard;
  914.             else
  915.             {
  916.                 Clipboard clip=Toolkit.getDefaultToolkit().getSystemClipboard();
  917.                 Transferable contents=clip.getContents(null);
  918.                 if (contents!=null && contents.isDataFlavorSupported(DataFlavor.stringFlavor))
  919.                 {
  920.                     cliptext=(String)contents.getTransferData(DataFlavor.stringFlavor);
  921.                 }
  922.             }
  923.            
  924.             if (cliptext!=null)
  925.             {
  926.                 Molecule frag=MoleculeStream.readUnknown(new BufferedReader(new StringReader(cliptext)));
  927.                 if (frag!=null) editor.addArbitraryFragment(frag);
  928.             }
  929.         }
  930.         catch (UnsupportedFlavorException e)
  931.         {
  932.             JOptionPane.showMessageDialog(null,e.toString(),"Clipboard Read Failed",JOptionPane.ERROR_MESSAGE);
  933.         }
  934.         catch (IOException e)
  935.         {
  936.             JOptionPane.showMessageDialog(null,e.toString(),"Paste Failed",JOptionPane.ERROR_MESSAGE);
  937.         }
  938.     }
  939.  
  940.     void selectElement(String El)
  941.     {
  942.             if (lastElement!=null){
  943.                 if (lastElement.compareTo(El)==0) return;
  944.                 toolIcons[TOOL_SETATOM]=new ImageIcon(getClass().getResource("/images/"+IMAGE_TOOL[TOOL_SETATOM]+".png"));
  945.             }
  946.             int w=toolIcons[TOOL_SETATOM].getImage().getWidth(null),h=toolIcons[TOOL_SETATOM].getImage().getHeight(null);
  947.             BufferedImage img=new BufferedImage(w,h,BufferedImage.TYPE_INT_ARGB);
  948.             Graphics2D g=(Graphics2D)img.getGraphics();
  949.             g.setColor(new Color(0x00000000,true));
  950.             g.fillRect(0,0,w,h);
  951.             g.drawImage(toolIcons[TOOL_SETATOM].getImage(),0,0,null);
  952.             Font font=new Font("SansSerif",Font.PLAIN,El.length()==1 ? 20 : 14);
  953.             g.setFont(font);
  954.             g.setColor(new Color(0,192,0));
  955.             FontMetrics metrics=g.getFontMetrics();
  956.             g.drawString(El,(w-metrics.stringWidth(El))/2-3,(h+metrics.getAscent())/2-2);
  957.             toolButtons[TOOL_SETATOM].setIcon(new ImageIcon(img));
  958.             lastElement=El;
  959.     }
  960.    
  961.     void templateTool()
  962.     {
  963.         if (lastTemplate==null) {templateSelect(); return;}
  964.         editor.setToolTemplate(lastTemplate,templateIdx);
  965.     }
  966.    
  967.     void templateSelect()
  968.     {
  969.         int heightFudge=appletMode ? 30 : 0; // !! unpleasant hack which stands in for being a non-signed applet; correct at some point
  970.         TemplateSelector sel=new TemplateSelector(templ,this,heightFudge);
  971.         Point pos=toolButtons[TOOL_TEMPLATE].getLocationOnScreen();
  972.  
  973.         Dimension ssz=Toolkit.getDefaultToolkit().getScreenSize();
  974.         GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment();
  975.         GraphicsConfiguration gc=ge.getScreenDevices()[0].getConfigurations()[0];
  976.         ssz.width-=Toolkit.getDefaultToolkit().getScreenInsets(gc).right;
  977.         ssz.height-=Toolkit.getDefaultToolkit().getScreenInsets(gc).bottom;
  978.                
  979.         if (pos.x+sel.getWidth()>ssz.width) pos.x=ssz.width-sel.getWidth();
  980.         if (pos.y+sel.getHeight()>ssz.height) pos.y=ssz.height-sel.getHeight();
  981.         sel.setLocation(pos);
  982.         sel.setVisible(true);
  983.     }
  984.    
  985.     void templateAddTo()
  986.     {
  987.         templ.addTemplate(editor.selectedSubgraph());
  988.     }
  989.    
  990.     void editDialog()
  991.     {
  992.         Molecule newMol=(new DialogEdit(frameParent,editor.molData(),editor.selectedIndices())).exec();
  993.         if (newMol!=null)
  994.         {
  995.             editor.cacheUndo();
  996.             editor.replace(newMol,false);
  997.         }
  998.     }
  999.    
  1000.     void helpAbout()
  1001.     {
  1002.         String msg="WIMSchem v"+VERSION+"\n"+
  1003.                    "Molecule drawing tool\n"+
  1004.                    "© 2005-2008 Dr. Alex M. Clark\n"+
  1005.                    "Released under the Gnu Public\n"+
  1006.                    "License (GPL), see www.gnu.org\n"+
  1007.                    "Home page and documentation:\n"+
  1008.                    "http://sketchel.sf.net\n"+
  1009.                    "Modified for WIMS\n"+
  1010.                    "jm.evers 2009";
  1011.         JOptionPane.showMessageDialog(null,msg,"About WIMSchem",JOptionPane.INFORMATION_MESSAGE,mainLogo);
  1012.     }
  1013.    
  1014.     // ------------------ event functions --------------------
  1015.  
  1016.     public void actionPerformed(ActionEvent e)
  1017.     {
  1018.         String cmd=e.getActionCommand();
  1019.        
  1020.         int setsel=-1;
  1021.        
  1022.         if (cmd.equals(translation.getProperty("Quit")) || cmd.equals(translation.getProperty("Close")) || cmd.equals(translation.getProperty("Save_and_Quit"))) fileQuit();
  1023.         else if (cmd.equals(translation.getProperty("New"))) fileNew();
  1024.         else if (cmd.equals(translation.getProperty("New_Window"))) fileNewWindow();
  1025.         else if (cmd.equals(translation.getProperty("New_DataSheet"))) fileNewDataSheet();
  1026.         else if (cmd.equals(translation.getProperty("Open"))) fileOpen();
  1027.         else if (cmd.equals(translation.getProperty("Save"))) fileSave();
  1028.         else if (cmd.equals(translation.getProperty("Save_As"))) fileSaveAs();
  1029.         else if (cmd.equals(translation.getProperty("as_MDL_MOL"))) fileExportMDLMOL();
  1030.         else if (cmd.equals(translation.getProperty("as_CML_XML"))) fileExportCMLXML();
  1031.         else if (cmd.equals(translation.getProperty("as_SVG"))) fileExportSVG();
  1032.         else if (cmd.equals(translation.getProperty("Cursor")) || e.getSource()==toolButtons[TOOL_CURSOR]) {editor.setToolCursor(); setsel=TOOL_CURSOR;}
  1033.         else if (cmd.equals(translation.getProperty("Rotator")) || e.getSource()==toolButtons[TOOL_ROTATOR]) {editor.setToolRotator(); setsel=TOOL_ROTATOR;}
  1034.         else if (cmd.equals(translation.getProperty("Erasor")) || e.getSource()==toolButtons[TOOL_ERASOR]) {editor.setToolErasor(); setsel=TOOL_ERASOR;}
  1035.         else if (cmd.equals(translation.getProperty("Editttt")) || e.getSource()==toolButtons[TOOL_DIALOG]) editDialog();
  1036.         else if (cmd.equals(translation.getProperty("Select_All"))) editor.selectAll();
  1037.         else if (cmd.equals(translation.getProperty("Next_Atom"))) editor.cycleSelection(true,false);
  1038.         else if (cmd.equals(translation.getProperty("Previous_Atom"))) editor.cycleSelection(false,false);
  1039.         else if (cmd.equals(translation.getProperty("Next_Group"))) editor.cycleSelection(true,true);
  1040.         else if (cmd.equals(translation.getProperty("Previous_Group"))) editor.cycleSelection(false,true);
  1041.         else if (cmd.equals(translation.getProperty("Edit_Atom")) || e.getSource()==toolButtons[TOOL_EDIT]) {editor.setToolAtom(null); setsel=TOOL_EDIT;}
  1042.         else if (cmd.equals(translation.getProperty("Set_Atom")) || e.getSource()==toolButtons[TOOL_SETATOM]) {editor.setToolAtom(lastElement); setsel=TOOL_SETATOM;}
  1043.         else if (cmd.equals(translation.getProperty("Single_Bond")) || e.getSource()==toolButtons[TOOL_SINGLE]) {editor.setToolBond(1); setsel=TOOL_SINGLE;}
  1044.         else if (cmd.equals(translation.getProperty("Double_Bond")) || e.getSource()==toolButtons[TOOL_DOUBLE]) {editor.setToolBond(2); setsel=TOOL_DOUBLE;}
  1045.         else if (cmd.equals(translation.getProperty("Triple_Bond")) || e.getSource()==toolButtons[TOOL_TRIPLE]) {editor.setToolBond(3); setsel=TOOL_TRIPLE;}
  1046.         else if (cmd.equals(translation.getProperty("Zero_Bond")) || e.getSource()==toolButtons[TOOL_ZERO]) {editor.setToolBond(0); setsel=TOOL_ZERO;}
  1047.         else if (cmd.equals(translation.getProperty("Inclined_Bond")) || e.getSource()==toolButtons[TOOL_INCLINED]) {editor.setToolBond(-1); setsel=TOOL_INCLINED;}
  1048.         else if (cmd.equals(translation.getProperty("Declined_Bond")) || e.getSource()==toolButtons[TOOL_DECLINED]) {editor.setToolBond(-2); setsel=TOOL_DECLINED;}
  1049.         else if (cmd.equals(translation.getProperty("Unknown_Bond")) || e.getSource()==toolButtons[TOOL_UNKNOWN]) {editor.setToolBond(-3); setsel=TOOL_UNKNOWN;}
  1050.         else if (cmd.equals(translation.getProperty("Charge")) || e.getSource()==toolButtons[TOOL_CHARGE]) {editor.setToolCharge(1); setsel=TOOL_CHARGE;}
  1051.         else if (cmd.equals(translation.getProperty("Undo")) || e.getSource()==toolButtons[TOOL_UNDO]) editor.undo();
  1052.         else if (cmd.equals(translation.getProperty("Redo")) || e.getSource()==toolButtons[TOOL_REDO]) editor.redo();
  1053.         else if (cmd.equals(translation.getProperty("Un_select_all")) || e.getSource()==toolButtons[TOOL_UNSELECT]) editor.deSelectAll();
  1054.         else if (cmd.equals(translation.getProperty("Select")) || e.getSource()==toolButtons[TOOL_SELECT]) editor.Select();
  1055.         else if (cmd.equals(translation.getProperty("Cut"))) editCut();
  1056.         else if (cmd.equals(translation.getProperty("Copy"))) editCopy();
  1057.         else if (cmd.equals(translation.getProperty("Copy_SVG"))) editCopySVG();
  1058.         else if (cmd.equals(translation.getProperty("Paste"))) editPaste();
  1059.         else if (cmd.equals(translation.getProperty("Flip_Horizontal"))) editor.flipSelectedAtoms(false);
  1060.         else if (cmd.equals(translation.getProperty("Flip_Vertical"))) editor.flipSelectedAtoms(true);
  1061.         else if (cmd.equals(translation.getProperty("Rotate_P45"))) editor.rotateSelectedAtoms(45);
  1062.         else if (cmd.equals(translation.getProperty("Rotate_M45"))) editor.rotateSelectedAtoms(-45);
  1063.         else if (cmd.equals(translation.getProperty("Rotate_P90"))) editor.rotateSelectedAtoms(90);
  1064.         else if (cmd.equals(translation.getProperty("Rotate_M90"))) editor.rotateSelectedAtoms(-90);
  1065.         else if (cmd.equals(translation.getProperty("Add_Temporary_Template"))) templateAddTo();
  1066.         else if (cmd.equals(translation.getProperty("Normalise_Bond_Lengths"))) editor.normaliseBondLengths();
  1067.         else if (cmd.equals(translation.getProperty("Template_Tool")) || e.getSource()==toolButtons[TOOL_TEMPLATE]) {templateTool(); setsel=TOOL_TEMPLATE;}
  1068.         else if (cmd.equals(translation.getProperty("Select_Template"))) {templateSelect(); setsel=TOOL_TEMPLATE;}
  1069.         else if (cmd.equals(translation.getProperty("Zoom_Full"))) editor.zoomFull();
  1070.         else if (cmd.equals(translation.getProperty("Zoom_In"))) editor.zoomIn(1.5);
  1071.         else if (cmd.equals(translation.getProperty("Zoom_Out"))) editor.zoomOut(1.5);
  1072.         else if (cmd.equals(translation.getProperty("Show_Elements"))) editor.setShowMode(ArrangeMolecule.SHOW_ELEMENTS);
  1073.         else if (cmd.equals(translation.getProperty("Show_All_Elements"))) editor.setShowMode(ArrangeMolecule.SHOW_ALL_ELEMENTS);
  1074.         else if (cmd.equals(translation.getProperty("Show_Indices"))) editor.setShowMode(ArrangeMolecule.SHOW_INDEXES);
  1075.         else if (cmd.equals(translation.getProperty("Show_Ring_ID"))) editor.setShowMode(ArrangeMolecule.SHOW_RINGID);
  1076.         else if (cmd.equals(translation.getProperty("Show_CIP_Priority"))) editor.setShowMode(ArrangeMolecule.SHOW_PRIORITY);
  1077.         else if (cmd.equals(translation.getProperty("Show_Mapping_Number"))) editor.setShowMode(ArrangeMolecule.SHOW_MAPNUM);
  1078.         else if (cmd.equals(translation.getProperty("Show_Hydrogen"))) editor.setShowHydrogens(chkShowHydr.isSelected());
  1079.         else if (cmd.equals(translation.getProperty("Set_Explicit")))  editor.hydrogenSetExplicit(true);
  1080.         else if (cmd.equals(translation.getProperty("Clear_Explicit"))) editor.hydrogenSetExplicit(false);
  1081.         else if (cmd.equals(translation.getProperty("Zero_Explicit"))) editor.hydrogenSetExplicit(false,0);
  1082.         else if (cmd.equals(translation.getProperty("Create_Actual"))) editor.hydrogenCreateActual();
  1083.         else if (cmd.equals(translation.getProperty("Delete_Actual"))) editor.hydrogenDeleteActual();
  1084.         else if (cmd.equals(translation.getProperty("Show_Stereolabels"))) editor.setShowStereolabels(chkShowSter.isSelected());
  1085.         else if (cmd.equals(translation.getProperty("Invert_Stereochemistry"))) editor.setStereo(Molecule.STEREO_UNKNOWN);
  1086.         else if (cmd.equals(translation.getProperty("Set_R/Z"))) editor.setStereo(Molecule.STEREO_POS);
  1087.         else if (cmd.equals(translation.getProperty("Set_S/E"))) editor.setStereo(Molecule.STEREO_NEG);
  1088.         else if (cmd.equals(translation.getProperty("Cycle_Wedges"))) editor.cycleChiralWedges();
  1089.         else if (cmd.equals(translation.getProperty("Remove_Wedges"))) editor.removeChiralWedges();
  1090.         else if (cmd.equals(translation.getProperty("About"))) helpAbout();
  1091.         else if (TOOL_SELECTION[TOOL_SETATOM] && cmd.length()<=2) {selectElement(cmd); editor.setToolAtom(lastElement);}
  1092.         if (setsel!=-1) toolGroup.setSelected(toolButtons[setsel].getModel(),true);
  1093.     }
  1094.    
  1095.     public void mouseClicked(MouseEvent e) {}
  1096.     public void mouseEntered(MouseEvent e) {}
  1097.     public void mouseExited(MouseEvent e) {}
  1098.     public void mousePressed(MouseEvent e)
  1099.     {
  1100.         if (e.getSource()==toolButtons[TOOL_SETATOM] && e.getButton()==MouseEvent.BUTTON3)
  1101.         {
  1102.             toolButtons[TOOL_SETATOM].setSelected(true);
  1103.             JPopupMenu popup=new JPopupMenu();
  1104.             int max = myAtoms.length;
  1105.             for(int i=0 ; i < max ;i++ ){
  1106.              popup.add(menuItem( myAtoms[i] ,0));
  1107.             }
  1108.             popup.show(toolButtons[TOOL_SETATOM],0,0);
  1109.         }
  1110.         if (e.getSource()==toolButtons[TOOL_TEMPLATE] && e.getButton()==MouseEvent.BUTTON3)
  1111.         {
  1112.             toolGroup.setSelected(toolButtons[TOOL_TEMPLATE].getModel(),true);
  1113.             templateSelect();
  1114.         }
  1115.     }
  1116.     public void mouseReleased(MouseEvent e) {}  
  1117.     public void keyPressed(KeyEvent e)
  1118.     {
  1119.         // keyboard arrow-nudges
  1120.         if (!e.isAltDown() && !e.isShiftDown() && !e.isControlDown() && !e.isMetaDown())
  1121.         {
  1122.             if (e.getKeyCode()==KeyEvent.VK_UP) {editor.nudgeSelectedAtoms(0,0.05); return;}
  1123.             if (e.getKeyCode()==KeyEvent.VK_DOWN) {editor.nudgeSelectedAtoms(0,-0.05); return;}
  1124.             if (e.getKeyCode()==KeyEvent.VK_LEFT) {editor.nudgeSelectedAtoms(-0.05,0); return;}
  1125.             if (e.getKeyCode()==KeyEvent.VK_RIGHT) {editor.nudgeSelectedAtoms(0.05,0); return;}
  1126.         }
  1127.     }
  1128.     public void keyReleased(KeyEvent e) {}
  1129.     public void keyTyped(KeyEvent e)
  1130.     {    
  1131.         // user typing in an element...
  1132.         char ch=e.getKeyChar();
  1133.         if (ch>='A' && ch<='Z') typedElement=""+ch;
  1134.         else if (typedElement.length()==1 && ch>='a' && ch<='z') typedElement=typedElement+ch;
  1135.         else if (typedElement.compareTo("R")==0 && ch>='0' && ch<='9') typedElement=typedElement+ch;
  1136.         else {typedElement=""; return;}
  1137.  
  1138.         String elset=null;
  1139.         if (typedElement.length()>=2 && typedElement.charAt(0)=='R' && typedElement.charAt(1)>='0' && typedElement.charAt(1)<='9')
  1140.         {
  1141.             elset=typedElement;
  1142.         }
  1143.         else
  1144.         {
  1145.             for (int n=1;n<Molecule.ELEMENTS.length;n++) if (typedElement.compareTo(Molecule.ELEMENTS[n])==0) {elset=typedElement;}
  1146.         }
  1147.         if (elset!=null)
  1148.         {
  1149.             selectElement(elset);
  1150.             toolGroup.setSelected(toolButtons[TOOL_SETATOM].getModel(),true);
  1151.             editor.setToolAtom(elset);
  1152.         }
  1153.     }
  1154.    
  1155.     public void templSelected(Molecule mol,int idx)
  1156.     {
  1157.         lastTemplate=mol;
  1158.         templateIdx=idx;
  1159.         editor.setToolTemplate(mol,idx);
  1160.     }
  1161.     public void molSelected(EditorPane source,int idx,boolean dblclick)
  1162.     {
  1163.         if (dblclick && idx!=0)
  1164.         {
  1165.             ArrayList<Integer> selidx=new ArrayList<Integer>();
  1166.             if (idx>0) selidx.add(idx);
  1167.             else {selidx.add(editor.molData().bondFrom(-idx)); selidx.add(editor.molData().bondTo(-idx));}
  1168.             Molecule newMol=(new DialogEdit(frameParent,editor.molData(),selidx)).exec();
  1169.             if (newMol!=null) editor.replace(newMol);
  1170.         }
  1171.     }
  1172.     public void dirtyChanged(boolean isdirty)
  1173.     {
  1174.         String str=frameParent==null ? "WIMSchem" : frameParent.getTitle();
  1175.         if (str.charAt(0)=='*') str=str.substring(1);
  1176.         if (isdirty) str="*"+str;
  1177.         if (frameParent!=null && saver==null) frameParent.setTitle(str);
  1178.     }
  1179.    
  1180.     public void lostOwnership(Clipboard clipboard,Transferable contents) {} // don't care
  1181.    
  1182.     public void windowActivated(WindowEvent e) {}
  1183.     public void windowClosed(WindowEvent e) {}
  1184.     public void windowClosing(WindowEvent e)
  1185.     {
  1186.         fileQuit();
  1187.     }
  1188.     public void windowDeactivated(WindowEvent e) {}
  1189.     public void windowDeiconified(WindowEvent e) {}
  1190.     public void windowIconified(WindowEvent e) {}
  1191.     public void windowOpened(WindowEvent e)
  1192.     {
  1193.         if (firstResize)
  1194.         {
  1195.             editor.scaleToFit();
  1196.             editor.repaint();
  1197.             firstResize=false;
  1198.         }
  1199.         editor.requestFocusInWindow();
  1200.     }
  1201.    
  1202.     public  String getToolTips( int p ){
  1203.         switch(p){
  1204.          case 0: return translation.getProperty("CURSOR_TIP");
  1205.          case 1: return translation.getProperty("ROTATOR_TIP");
  1206.          case 2: return translation.getProperty("ERASOR_TIP");
  1207.          case 3: return translation.getProperty("EDIT_DIALOG_TIP");
  1208.          case 4: return translation.getProperty("EDIT_ELEMENT_TIP");
  1209.          case 5: return translation.getProperty("PLACE_ELEMENT_TIP");
  1210.          case 6: return translation.getProperty("SINGLE_BOND_TIP");
  1211.          case 7: return translation.getProperty("DOUBLE_BOND_TIP");
  1212.          case 8: return translation.getProperty("TRIPLE_BOND_TIP");
  1213.          case 9: return translation.getProperty("ZERO_BOND_TIP");
  1214.          case 10: return translation.getProperty("INCLINED_BOND_TIP");
  1215.          case 11: return translation.getProperty("DECLINE_BOND_TIP");
  1216.          case 12: return translation.getProperty("SQUIGGLY_BOND_TIP");
  1217.          case 13: return translation.getProperty("CHARGE_TIP");
  1218.          case 14: return translation.getProperty("UNDO_TIP");
  1219.          case 15: return translation.getProperty("REDO_TIP");
  1220.          case 16: return translation.getProperty("TEMPLATE_TIP");
  1221.          case 17: return translation.getProperty("CUT_TIP");
  1222.          case 18: return translation.getProperty("COPY_TIP");
  1223.          case 19: return translation.getProperty("PASTE");
  1224.          case 20: return translation.getProperty("SELECT");
  1225.          case 21: return translation.getProperty("UNSELECT");
  1226.          default : return "NO TIP?";
  1227.         }
  1228.     }
  1229.     private Properties loadProperties(String lang){
  1230.      Properties P=new Properties();
  1231.      try{
  1232.       InputStream in = getClass().getResourceAsStream("/lang/WIMSchemProperties_"+lang+".properties");
  1233.       P.load(in);in.close();
  1234.       return P;
  1235.      }catch (Exception e){ System.out.println("error reading /lang/WIMSchemProperties_"+lang+".properties\n"+e);}
  1236.      return null;
  1237.     }
  1238.        
  1239.  
  1240. }
  1241.