Subversion Repositories wimsdev

Rev

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

  1. /*
  2.     Sketch Elements: Chemistry molecular diagram drawing tool.
  3.    
  4.     (c) 2005 Dr. Alex M. Clark
  5.    
  6.     Released as GNUware, under the Gnu Public License (GPL)
  7.    
  8.     See www.gnu.org for details.
  9.  
  10.    
  11.     11/2013 rewrite based on SketchEl 1.21: (08/Nov/2008) to include export of SVG.
  12.    
  13.     More recent verions than 1.21 do not improve the Applet or SVG export.
  14.    
  15.     jm.evers
  16. */  
  17. package WIMSchem;
  18.  
  19. import java.io.*;
  20. import java.awt.*;
  21. import java.awt.event.*;
  22. import java.util.*;
  23. import javax.swing.*;
  24. import java.net.*;
  25. import java.applet.AppletContext;
  26. import java.text.*;
  27.  
  28. public class MainApplet extends JApplet implements ComponentListener
  29. {
  30.     MainPanel mainPanel=null;
  31.     long id;
  32.     String zoom_js;
  33.     public static String g_id = "g_SVG_1000000";/* used for SVG zoom in/out */
  34.     public static String svg_id = "SVG_1000000";/* used for SVG zoom in/out */
  35.     /* jm.evers addition to configure applet */
  36.     static String[] TOOLS={"TOOL_CURSOR","TOOL_ROTATOR","TOOL_ERASOR","TOOL_DIALOG","TOOL_EDIT",
  37.     "TOOL_SETATOM","TOOL_SINGLE","TOOL_DOUBLE","TOOL_TRIPLE","TOOL_ZERO",
  38.     "TOOL_INCLINED","TOOL_DECLINED","TOOL_UNKNOWN","TOOL_CHARGE","TOOL_UNDO",
  39.     "TOOL_REDO","TOOL_TEMPLATE","TOOL_CUT","TOOL_COPY","TOOL_PASTE",
  40.     "TOOL_UNSELECT","TOOL_SELECT"};
  41.     static String[] MENUS={"MENU_BLOCK","MENU_SELECT","MENU_TRANSFORM","MENU_ZOOM","MENU_SHOW","MENU_HYDROGEN","MENU_STEREO","MENU_HELP"};
  42.     static int TOOL_COUNT = TOOLS.length;
  43.     static int MENU_COUNT = MENUS.length;
  44.     public static String[] templateURL;
  45.     public static AppletContext applet_context;
  46.     public static String[] myAtoms;
  47.     public static int rotation;
  48.     public static boolean viewC;
  49.     public static boolean viewH;
  50.     public static boolean[] TOOL_SELECTION;
  51.     public static boolean[] MENU_SELECTION;
  52.     public static boolean USER_SELECTION = false;
  53.     public static int GLOBAL_ALPHA = 140;
  54.     public static int ATOM_SELECT_HTML_COLOR; /* the default Atom click colour for user interaction when selecting atoms */
  55.     public static int BOND_SELECT_HTML_COLOR; /* the default bond click colour for user interaction when selecting atoms */
  56.     public static Color ATOM_SELECT_COLOR;/* the colour for not-by-param-selected-atoms */
  57.     public static Color BOND_SELECT_COLOR;/* the colour for not-by-param-selected-bonds */
  58.     public static int[] ExternalAtomSelection; /* atom line numbers in MDLmol file */
  59.     public static Color SelectedAtomColorArray[];/* atom corresponding colours for line numbers in MDLmol file */
  60.     public static int[] ExternalBondSelection;/* bonding line numbers in MDLmol file */
  61.     public static Color SelectedBondColorArray[];;/* corresponding bonding colours for line numbers in MDLmol file */
  62.     public static int SelectedAtomColorInt[]; /* int color numbers set by params used in svg export */
  63.     public static int SelectedBondColorInt[]; /* colors set by params used in svg export */
  64.     public static boolean ATOM_BUTTONS = true; /* button row with atoms SOUTH */
  65.     public static boolean SUPERUSER_SELECTION = false; /* if true the exported SVG will be coloured according params */
  66.    
  67.     public static String language;
  68.     public void init(){
  69.         ATOM_BUTTONS = getBool("atom_button_row",false); /* if set an extra row of buttons will be shown  */
  70.         USER_SELECTION = getBool("user_selection",false);
  71.         if( USER_SELECTION ){
  72.             GLOBAL_ALPHA = getInt("color_alpha",140);
  73.             /* some people forget the importance of alpha...this should be removed */
  74.             if( GLOBAL_ALPHA > 250 ){GLOBAL_ALPHA = 140;}
  75.             ATOM_SELECT_COLOR = getColor("default_atom_select_color",GLOBAL_ALPHA,255,0,0);/* RGB */
  76.             BOND_SELECT_COLOR = getColor("default_bond_select_color",GLOBAL_ALPHA,0,0,255);/* RGB */
  77.             ATOM_SELECT_HTML_COLOR = RGB2int("default_atom_select_color",0x0000ff);/* int for svg */
  78.             BOND_SELECT_HTML_COLOR = RGB2int("default_bond_select_color",0x00ff00);/* int for svg */
  79.         }
  80.         zoom_js = "";
  81.         language = getLanguage();
  82.         TOOL_SELECTION = getTools();
  83.         MENU_SELECTION = getMenus();
  84.         ExternalAtomSelection = SetAtomSelection();
  85.         ExternalBondSelection = SetBondSelection();
  86.         rotation = getInt("rotation",0);
  87.         myAtoms = GetMyAtoms(); /* read parm atoms to tailomade atomselection*/
  88.         templateURL = getTemplateURL();/* read params template1...template_n and use these insteadof default ones */
  89.         viewC =  getBool("show_carbon",true);
  90.         viewH = getBool("show_hydrogen",true);
  91.         System.out.println("viewC = "+viewC+"\nviewH = "+viewH);
  92.         getContentPane().setLayout(new BorderLayout());
  93.         mainPanel=new MainPanel(null,MainPanel.MODE_APPLET,null);
  94.         getContentPane().add(mainPanel,BorderLayout.CENTER);
  95.         addComponentListener(this);
  96.         getFile();/* read param file and load it if param showfile is set */
  97.         repaint(1000);
  98.     }
  99.     public String getAppletInfo()
  100.     {
  101.         return "WIMSchem: Applet version of chemistry\nmolecular diagram drawing tool.";
  102.     }
  103.  
  104.     /*
  105.         replace the current molecule with the content of the string, which can be any of the formats which WIMSchem
  106.         is able to read out from a file; returns true if successful
  107.     */
  108.     public boolean SetMoleculeNative(String Source) {
  109.         try{
  110.             Molecule mol=MoleculeStream.readNative(new BufferedReader(new StringReader(Source.toString())));
  111.             mainPanel.setMolecule(mol);
  112.             mainPanel.repaint();
  113.             return true;
  114.         } catch (IOException e) { System.out.println("problems parsing:\n"+Source.toString()+"\n"+e);}
  115.         return false;
  116.     }
  117.     public boolean SetMoleculeMDLMol(String Source){
  118.         try{
  119.             Molecule mol = MoleculeStream.readMDLMOL(new BufferedReader(new StringReader(Source.toString())));
  120.             mainPanel.setMolecule(mol);
  121.             mainPanel.repaint();
  122.             return true;
  123.         } catch (IOException e) { System.out.println("problems parsing:\n"+Source.toString()+"\n"+e);}
  124.         return false;
  125.     }
  126.     public boolean SetMolecule(String Source, boolean is_molfile)
  127.     {
  128.         try
  129.         {
  130.             Molecule mol;
  131.             if(is_molfile){
  132.              mol = MoleculeStream.readMDLMOL(new BufferedReader(new StringReader(Source.toString())));
  133.             }
  134.             else
  135.             {
  136.              mol = MoleculeStream.readUnknown(new BufferedReader(new StringReader(Source.toString())));
  137.             }
  138.             mainPanel.setMolecule(mol);
  139.             mainPanel.repaint();
  140.             return true;
  141.         }
  142.         catch (IOException e){ System.out.println("error in applet : setMolecule( String Source ) :\ncan not parse : "+Source.toString());}
  143.         return false;
  144.     }
  145.    
  146.     /*
  147.         appends the indicated molecular source to the current molecule,
  148.         in the same way as the paste feature; otherwise works
  149.         the same as SetMolecule
  150.     */
  151.     public boolean AppendMolecule(String Source, boolean is_molfile)
  152.     {
  153.         try
  154.         {
  155.             Molecule mol;
  156.             if(is_molfile){
  157.              mol = MoleculeStream.readMDLMOL(new BufferedReader(new StringReader(Source.toString())));
  158.             }
  159.             else
  160.             {
  161.              mol = MoleculeStream.readUnknown(new BufferedReader(new StringReader(Source.toString())));
  162.             }
  163.             mainPanel.addMolecule(mol);
  164.             mainPanel.repaint();
  165.             return true;
  166.         }
  167.         catch (IOException e) { System.out.println("error in applet : appendMolelcule( String Source ) : "+e.toString());}
  168.        
  169.         return false;
  170.     }
  171.    
  172.     /*
  173.         return the string representation of the molecule, in WIMSchem native format
  174.     */
  175.     public String GetMoleculeNative()
  176.     {
  177.         try
  178.         {
  179.             StringWriter sw=new StringWriter();
  180.             BufferedWriter bw=new BufferedWriter(sw);
  181.             MoleculeStream.writeNative(bw,mainPanel.molData());
  182.             return sw.toString();
  183.         }
  184.         catch (IOException e) {}
  185.        
  186.         return null;
  187.     }
  188.    
  189.     /*
  190.         return the string representation of the molecule, in MDL MOL-file format
  191.     */
  192.     public String GetMoleculeMDLMol()
  193.     {
  194.         try
  195.         {
  196.             StringWriter sw = new StringWriter();
  197.             BufferedWriter bw = new BufferedWriter(sw);
  198.             MoleculeStream.writeMDLMOL(bw,mainPanel.molData());
  199.             return sw.toString();
  200.         }
  201.         catch (IOException e) {}
  202.        
  203.         return "error getting MDLMol file from applet";
  204.     }
  205.     public int RGB2int(String p, int d){ /* convert 255,0,255 -> ff00ff*/
  206.         String param = getParameter(p);
  207.         if( param != null && param.length()>0 ){
  208.             int k = 0;String hex = "";String tmp="";
  209.             StringTokenizer q = new StringTokenizer(param, ",");
  210.             int c = q.countTokens();
  211.             if( c != 3){System.out.println("use R,G,B for colours ; use param color_alpha for transparency"); return d;}
  212.             for( int a = 0; a < 3 ; a++){
  213.                 k = Integer.parseInt(q.nextToken(), 10);
  214.                 tmp = Integer.toHexString(k);
  215.                 while (tmp.length()<2) tmp="0"+tmp;
  216.                 hex = hex+""+tmp;
  217.             }
  218.             return Integer.parseInt(hex,16);
  219.         }
  220.         else
  221.         {
  222.             return d;
  223.         }
  224.     }
  225.  
  226.     public void componentHidden(ComponentEvent e){}
  227.     public void componentMoved(ComponentEvent e){}
  228.     public void componentResized(ComponentEvent e){}
  229.     public void componentShown(ComponentEvent e){
  230.         mainPanel.scaleToFit();
  231.         mainPanel.repaint();
  232.     }
  233.     /*
  234.         jm.evers additions to configuring applet
  235.     */
  236.     public String getSelected(){
  237.         int num=0;
  238.         String reply="";
  239.         Molecule mol = (mainPanel.editor).molData();
  240.         for (int n=1;n<mol.numAtoms();n++){
  241.             if( (mainPanel.editor).selected[n-1] ){ reply = reply+mol.atomElement(n-1)+"\n";}
  242.         }
  243.         return reply;
  244.     }
  245.    
  246.     public String getSVG(String type){
  247.         SVGMolecule svgmol;
  248.         if( type.equals("1") ){ /* get the student reply*/
  249.             try{
  250.                 System.out.println("ok : exporting user drawing to SVG");
  251.                 svgmol = new SVGMolecule((mainPanel.editor).molData());
  252.             }catch(Exception e){return e.toString();}
  253.         }
  254.         else
  255.         {
  256.          /*
  257.              check if we have a param 'name=file2' : reserved for the correctmolecule in mdlmol --> svg
  258.              using javascript:getSVG(2)
  259.          */
  260.             type = getString("file2");
  261.             USER_SELECTION = false; /* disable colours of studentreply in correct answer svg ! */    
  262.             SUPERUSER_SELECTION = true; /* if appropriate set html colours to applet colours */
  263.             if( type != null ){ /* ok found param file2 */
  264.                 try{
  265.                     String correct_answer = loadAny(type);
  266.                     Molecule answer_mol = MoleculeStream.readMDLMOL(new BufferedReader(new StringReader(correct_answer.toString())));
  267.                     svgmol = new SVGMolecule(answer_mol);
  268.                     System.out.println("ok : exporting file2 to SVG");
  269.                 }catch(Exception e){return e.toString();}
  270.             }
  271.             else
  272.             {
  273.                 /* use the drawing in the applet for export to svg*/
  274.                 try{
  275.                     svgmol = new SVGMolecule((mainPanel.editor).molData());
  276.                     System.out.println("ok : exporting molecule in applet window to SVG\npossibly colouring atoms and bonds\naccording to color params");
  277.                 }catch(Exception e){return e.toString();}
  278.             }
  279.         }
  280.         double zoom_factor = getDouble("zoomfactor",1.00);
  281.         if( zoom_factor != 1.00 ){ /* simple static in/out zoom, no pan */
  282.             id = System.currentTimeMillis();
  283.             g_id = ("g_SVG_"+id).toString();
  284.             svg_id = ("SVG_"+id).toString();
  285.             zoom_js="<script type=\"text/javascript\">"+
  286.             "var flip = 0;"+
  287.             "function SVG_zoom(svg,g,w0,h0){"+
  288.              "var svg = document.getElementById(svg);"+
  289.              "var g = document.getElementById(g);"+
  290.              "var f = "+zoom_factor+";"+
  291.              "if( flip == 1 ){"+
  292.               "flip = 0;"+
  293.               "var w1 = parseInt(w0*f);"+
  294.               "var h1 = parseInt(h0*f);"+
  295.               "svg.setAttributeNS(null, 'viewBox', '0 0 '+w1+' '+h1);"+
  296.               "svg.setAttributeNS(null, 'width',w1);"+
  297.               "svg.setAttributeNS(null, 'height',h1);"+
  298.               "g.setAttributeNS(null,'transform','matrix('+f+' 0 0 '+f+' 0 0)');"+
  299.              "}else{"+
  300.               "flip = 1;"+
  301.               "svg.setAttributeNS(null, 'viewBox', '0 0 '+w0+' '+h0);"+
  302.               "svg.setAttributeNS(null, 'width',w0);"+
  303.               "svg.setAttributeNS(null, 'height',h0);"+
  304.               "g.setAttributeNS(null,'transform','matrix(1 0 0 1 0 0)');"+
  305.               "};};</script>";
  306.         }
  307.         svgmol.draw();
  308.         String reply = "";
  309.         reply = (svgmol + zoom_js).toString();
  310.         return reply.replaceAll("(\\n|\\r|\\  )", " ");
  311.     }
  312.    
  313.     public boolean[] getTools(){ /* jm.evers: configuring toolbar through appletparams  */
  314.      String param;
  315.      boolean[] TOOL_SELECTION = new boolean[TOOL_COUNT];
  316.      for(int p = 0;p < TOOL_COUNT ; p++){ /* adjust if more buttons are added MainPanel */
  317.       param = getParameter(TOOLS[p]);
  318.       TOOL_SELECTION[p] = false;
  319.       if( param != null ){if(param.equalsIgnoreCase("yes") || param.equals("1")){ TOOL_SELECTION[p] = true;} }
  320.      }
  321.       return TOOL_SELECTION;
  322.     }
  323.  
  324.     public boolean[] getMenus(){ /* jm.evers: configuring menubar through appletparams  */
  325.      String param;
  326.      boolean[] MENU_SELECTION = new boolean[MENU_COUNT];
  327.      for(int p = 0;p < MENU_COUNT ; p++){ /* adjust if more buttons are added MainPanel */
  328.       param = getParameter(MENUS[p]);
  329.       MENU_SELECTION[p] = false;
  330.       if( param != null && param.length() > 0){if(param.equalsIgnoreCase("yes") || param.equals("1")){ MENU_SELECTION[p] = true;} }
  331.      }
  332.       return MENU_SELECTION;
  333.     }
  334.    
  335.     public String[] getTemplateURL(){
  336.         // jm.evers : retreive an unknown amount of templates via params called template1,template2...
  337.         // these templates will be called by Template.java
  338.         String param = getParameter("template1");
  339.         if( param != null && param.length()>0 ){
  340.             int p=0;
  341.             while( param!=null && param.length()!=0 ){
  342.                 p++; /* unknown amount...let's count */
  343.                 param = getParameter("template"+p);
  344.             }
  345.             String[] templateURL = new String[p-1];
  346.             for(int s = 1;s < p; s++){ /* fill the array with url's */
  347.                 param = getParameter("template"+s);
  348.                 System.out.println("loading template url : "+param);
  349.                 templateURL[s - 1] = param;
  350.             }
  351.             return templateURL;
  352.         }
  353.         else
  354.         {
  355.             return null;
  356.         }
  357.     }
  358.    
  359.     public boolean getFile(){
  360.     /*
  361.         jm.evers : try to load a file as string from the URL given in the params
  362.     */
  363.         String showfile = getParameter("showfile");
  364.         if(showfile != null && showfile.length()>0){
  365.             if(showfile.equalsIgnoreCase("yes") ||  showfile.equals("1") ){
  366.                 String filename = getParameter("file");
  367.                 if (filename != null && filename.length() > 0){
  368.                 /*
  369.                     jm.evers: is param showfile is set, draw to canvas...
  370.                 */
  371.                     String demomol = loadAny(filename);
  372.                     if( demomol.indexOf("V2000") < 1 ){
  373.                         SetMolecule(demomol,false);
  374.                     }
  375.                     else
  376.                     {
  377.                         SetMolecule(demomol,true);
  378.                     }
  379.                     return true;
  380.                 }
  381.             }
  382.         }
  383.         else
  384.         {
  385.             System.out.println("not using external file loading");
  386.         }
  387.         return false;
  388.     }
  389.  
  390.     public String getString( String p ){
  391.         String param = getParameter(p);
  392.         if( param != null  && param.length()>0){
  393.             return  param.toString();
  394.         }
  395.         return null;
  396.     }
  397.     public Boolean getBool(String p , boolean d ){
  398.     /* jm.evers 27/12/2008 */
  399.         String param = getParameter(p);
  400.         if( param != null && param.length()>0 ){
  401.             param = param.toLowerCase();
  402.             if(param.equals("1") || param.equalsIgnoreCase("yes") || param.equalsIgnoreCase("true") ){
  403.                 return true;
  404.             }
  405.             if(param.equals("0") || param.equalsIgnoreCase("no") ||  param.equalsIgnoreCase("false")){
  406.                 return false;
  407.             }
  408.         }
  409.         return d;
  410.     }
  411.  
  412.     /*
  413.         routine to read an 'int' from some applet param 'p'
  414.     */
  415.     public int getInt(String p, int d){/* jm.evers 27/12/2008 */
  416.         String param = getParameter(p);
  417.         if( param != null  && param.length()>0){
  418.             return Integer.parseInt( param );
  419.         }
  420.         return d;
  421.         /*
  422.             we don't want to trip over a wrong param...use default
  423.         */
  424.     }
  425.     /*
  426.         routine to read a 'double' from some applet param 'p'
  427.     */
  428.     public double getDouble(String p, double d){/* jm.evers 27/12/2008 */
  429.         String param = getParameter(p);
  430.         if( param != null  && param.length()>0){
  431.             return Double.parseDouble( param );
  432.         }
  433.         return d;
  434.         /*
  435.             we don't want to trip over a wrong param...
  436.         */
  437.     }
  438.     /*
  439.         routine to read a color from some applet param 'p'
  440.     */
  441.     public Color getColor(String p, int alpha, int r0,int g0,int b0 ){
  442.         String param = getParameter(p);
  443.         if( param != null && param.length()>0){
  444.             String k;int R1=0,G1=0,B1=0,rgb=0;
  445.             StringTokenizer q = new StringTokenizer(param, ",");
  446.             int c = q.countTokens();
  447.             if( c != 3){System.out.println("use R,G,B for colours ; use param color_alpha for transparency"); return new Color(0,0,255,255);}
  448.             for( int a = 0; a < 3 ; a++){
  449.                 k = q.nextToken();
  450.                 rgb = Integer.parseInt(k, 10);
  451.                 if( rgb < 0 ){ rgb = 0; }
  452.                 if( rgb > 255 ){ rgb = 255; }
  453.                 if(a == 0){ R1 = rgb;}
  454.                 else
  455.                 if(a == 1){G1 = rgb;}
  456.                 else B1 = rgb;
  457.             }
  458.             return new Color(R1,G1,B1,alpha);
  459.         }
  460.         else
  461.         {
  462.             return new Color(r0,g0,b0,alpha);
  463.         }
  464.     }
  465.    
  466.     /*
  467.         jm.evers: reading atoms from params
  468.     */
  469.     public String[] GetMyAtoms(){
  470.         String param = getParameter("atoms");
  471.         if( param != null && param.length()>0){
  472.             return String2Array( param );
  473.         }
  474.         else
  475.         {
  476.             return null;
  477.         }
  478.     }
  479.     public String getLanguage(){
  480.     /*
  481.         jm.evers: reading language. default english
  482.     */
  483.      String param = getParameter("language");
  484.      if(param != null && param.length() == 2){return  param.toLowerCase();}
  485.      return "en";
  486.     }
  487.    
  488. /* called via javascript */
  489.     public String ReadAtomSelection(){
  490.      boolean[] S = EditorPane.atomselection;
  491.      String selection="";
  492.      for (int p = 1;p < S.length; p++){ /* starts with 1 */
  493.       if(S[p]){ /* is selected */
  494.        if(selection != ""){ selection = selection +","+p; } else { selection=""+p; }
  495.       }
  496.      }
  497.      return selection;
  498.     }
  499.     public String ReadBondSelection(){
  500.      boolean[] S = EditorPane.bondselection;
  501.       String selection="";
  502.       for (int p=0;p<S.length;p++){
  503.        if(S[p]){ /* is selected */
  504.         if(selection == ""){ selection = ""+p; } else { selection = selection+","+p; }
  505.        }
  506.       }
  507.       return selection;
  508.     }
  509.                
  510.  
  511. /* jm.evers : routines to load a file direct or via network */
  512.  
  513.     public String loadAny(String filename){
  514.      String demomol = "";
  515.      try{
  516.         return (load(filename)).toString();
  517.      }catch(Exception e){System.out.println("HMMMM");}
  518.      return demomol;
  519.     }
  520.     public static byte [] loadURL(URL url) throws IOException {
  521.         int bufSize = 1024 * 2;
  522.         byte [] buf = new byte[bufSize];
  523.         ByteArrayOutputStream bout = new ByteArrayOutputStream();
  524.         BufferedInputStream   in   = new BufferedInputStream(url.openStream());
  525.         int n;
  526.         while ((n = in.read(buf)) > 0) {
  527.             bout.write(buf, 0, n);
  528.         }
  529.         try
  530.         { in.close(); } catch (Exception ignored) { }
  531.         return bout.toByteArray();
  532.     }
  533.  
  534.     public static String loadFile(String fname) throws IOException {
  535.      try{
  536.         byte[] bytes = loadURL(new URL("file:" + fname));
  537.         return new String(bytes);
  538.      }catch(Exception e ){System.out.println("loadFile error :"+e.toString());}
  539.      return null;
  540.     }
  541.    
  542.     public static String load(String fileOrURL) throws IOException {
  543.         try {
  544.             URL url = new URL(fileOrURL);
  545.             return new String(loadURL(url));
  546.         } catch (Exception e) {
  547.         return loadFile(fileOrURL);
  548.         }
  549.     }
  550.    public String[] String2Array(String t){
  551.         /*
  552.             jm.evers: parsing params into array...fieldseparators are "," ":" ";" " "
  553.         */
  554.         StringTokenizer q;
  555.         if(t.indexOf(",")!=-1){
  556.             q = new StringTokenizer(t, ",");
  557.         }
  558.         else
  559.         {
  560.             if(t.indexOf(":")!=-1){
  561.                 q = new StringTokenizer(t, ":");
  562.             }
  563.             else
  564.             {
  565.                 if(t.indexOf(";")!=-1){
  566.                     q = new StringTokenizer(t, ";");
  567.                 }
  568.                 else
  569.                 {
  570.                     if(t.indexOf(" ")>2){
  571.                         q = new StringTokenizer(t, " ");
  572.                     }
  573.                     else
  574.                     {
  575.                         return null;
  576.                     }
  577.                 }
  578.             }
  579.         }
  580.         int max = q.countTokens();if( max > 50 ){ max = 50;}
  581.         String[] tmp = new String[max];String s="";
  582.         for( int p = 0 ; p<max ; p++){
  583.             s=q.nextToken();
  584.             if(s.length()==1 || s.length()==2){
  585.                 System.out.println("atom = "+s);
  586.                 tmp[p]=s;
  587.             }
  588.         }
  589.         return tmp;
  590.     }
  591.     public void send_to_wims(int type){
  592.     /*
  593.         DO NOT USE THIS FOR SENDING SVG/XML !!!
  594.         THIS WILL GIVE TROUBLE WIH TOO LARGE STRINGS:
  595.         [quote] The requested URL's length exceeds the capacity limit for this server.
  596.         BETTER USE:
  597.         <form  action="$wims_ref_name?form-data$session" method="post" enctype="multipart/form-data" >
  598.     */
  599.         applet_context = this.getAppletContext();
  600.         String wims_ref_name = getString("wims_ref_name");
  601.         String session = getString("session");
  602.         String module = getString("module");
  603.         String replyargs = getString("replyarguments"); /* reply2=*/
  604.         if( wims_ref_name == null ){
  605.             System.out.println("param wims_ref_name is not set POST will not work !!");
  606.         }
  607.         else
  608.         {
  609.             String student_MDL_molecule = GetMoleculeMDLMol();
  610.             String student_svg_molecule = getSVG("1");
  611.             String correct_svg_molecule = getSVG("2");
  612.             String reply = "";
  613.             switch(type){
  614.                 case 0: reply = student_MDL_molecule;break;
  615.                 case 1: reply = student_svg_molecule+"\n"+student_MDL_molecule;break;
  616.                 case 2: reply = correct_svg_molecule+"\n"+student_svg_molecule+"\n"+student_MDL_molecule;break;
  617.                 default: reply = "send_to_wims(type) \ntype=1: MDLmol student drawing\ntype=2: student SVG \\n MDLmol student drawing\ntype=3: answer SVG \\n student SVG \\n MDLmol student drawing ";
  618.             }
  619.             try{reply = URLEncoder.encode(reply,"UTF-8"); }catch(Exception e){reply = e.toString();}
  620.             String back_url_string = wims_ref_name+"?session="+session+"&module="+module+"&cmd=reply&"+replyargs;
  621.             back_url_string = back_url_string.replaceAll(" ",""); /* no space in url */
  622.             URL backurl;
  623.             try {backurl=new URL(back_url_string+reply);
  624.                 applet_context.showDocument(backurl,"_self");
  625.             } catch (MalformedURLException e){backurl=null;System.out.println("could not send  to wims "+back_url_string);}
  626.         }
  627.     }
  628.    
  629.     /*  
  630.         set bonds and atoms via applet param
  631.     */
  632.     public int[] SetAtomSelection(){
  633.         String param = getParameter("select_atoms");
  634.         if(param != null && param.length()>0){
  635.             String k;int rgb=0;int R1=255;int G1=0;int B1=0;//red
  636.             param=param.replaceAll(";",",");param=param.replaceAll(":",",");
  637.             StringTokenizer i = new StringTokenizer(param, ",");
  638.             int max=i.countTokens();
  639.             ExternalAtomSelection = new int[max];
  640.             SelectedAtomColorArray = new Color[max];
  641.             SelectedAtomColorInt = new int[max];
  642.             String ColorParam;
  643.             for(int p=0;p<max;p++){
  644.                 ExternalAtomSelection[p] = Integer.parseInt(i.nextToken());
  645.                 // now try to find the color belonging to this selected atom
  646.                 SelectedAtomColorInt[p] = RGB2int("select_atom_color"+ExternalAtomSelection[p]+"",0x00ff00);
  647.                 ColorParam=getParameter("select_atom_color"+ExternalAtomSelection[p]);
  648.                 if(ColorParam != null && ColorParam.length()>0){
  649.                     ColorParam=ColorParam.replaceAll(":",",");ColorParam=ColorParam.replace(";",",");
  650.                     StringTokenizer q = new StringTokenizer(ColorParam, ",");
  651.                     for( int a=0; a<3 ; a++){
  652.                         k=q.nextToken();
  653.                         rgb=Integer.parseInt(k, 10);
  654.                         if(rgb<0){rgb=0;}if(rgb>255){rgb=255;}
  655.                         if(a == 0){R1 = rgb;}
  656.                         else
  657.                         {
  658.                             if(a == 1){G1 = rgb;}
  659.                             else{B1 = rgb;}
  660.                         }
  661.                     }
  662.                     SelectedAtomColorArray[p] = new  Color(R1,G1,B1,GLOBAL_ALPHA);
  663.                 }
  664.                 else
  665.                 {
  666.                     SelectedAtomColorArray[p] = ATOM_SELECT_COLOR;
  667.                 }
  668.             }
  669.             SUPERUSER_SELECTION = true;
  670.         }else{ ExternalAtomSelection = null;}
  671.         return ExternalAtomSelection;
  672.     }
  673.  
  674.     /*  
  675.         set bonds and atoms via applet param
  676.     */
  677.     public int[] SetBondSelection(){
  678.         String param = getParameter("select_bonds");
  679.         if(param != null && param.length()>0){
  680.             String k;int rgb=0;int R1=255;int G1=0;int B1=0;String ColorParam;
  681.             param=param.replaceAll(";",",");param=param.replaceAll(":",",");
  682.             StringTokenizer i = new StringTokenizer(param, ",");
  683.             int max=i.countTokens();
  684.             ExternalBondSelection = new int[max];
  685.             SelectedBondColorArray = new Color[max];
  686.             SelectedBondColorInt = new int[max];
  687.             for(int p=0;p<max;p++){
  688.                 ExternalBondSelection[p] = Integer.parseInt(i.nextToken());
  689.                 // now try to find the color belonging to this selected bond
  690.                 SelectedBondColorInt[p] = RGB2int("select_bond_color"+ExternalBondSelection[p]+"",0x0000ff);
  691.                 ColorParam=getParameter("select_bond_color"+ExternalBondSelection[p]);
  692.                 if(ColorParam != null && ColorParam.length()>0){
  693.                     ColorParam=ColorParam.replaceAll(":",",");ColorParam=ColorParam.replace(";",",");
  694.                     StringTokenizer q = new StringTokenizer(ColorParam, ",");
  695.                     for( int a=0; a<3 ; a++){
  696.                         k=q.nextToken();
  697.                         rgb=Integer.parseInt(k, 10);
  698.                         if(rgb<0){rgb=0;}if(rgb>255){rgb=255;}
  699.                         if(a == 0){R1 = rgb;}
  700.                         else
  701.                         {
  702.                             if(a == 1){G1 = rgb;}
  703.                             else{B1 = rgb;}
  704.                         }
  705.                     }
  706.                     SelectedBondColorArray[p] = new  Color(R1,G1,B1,GLOBAL_ALPHA);
  707.                 }
  708.                 else
  709.                 {
  710.                     SelectedBondColorArray[p] = BOND_SELECT_COLOR;
  711.                 }
  712.             }
  713.             SUPERUSER_SELECTION = true;
  714.         }else{ ExternalBondSelection = null;}
  715.         return ExternalBondSelection;
  716.     }
  717.  
  718.     /*
  719.         return molecule data from current molecule in panel
  720.         returns 5 lines with  
  721.         line 1 : molweight      : eg 1 decimal, eg 123.4
  722.         line 2 : plain formula  : eg C5H4O2
  723.         line 3 : html formula   : eg C<sub>5</sub>H<sub>4</sub>O<sub>2</sub>
  724.         line 4 : plain formula  : eg C5H4O2 (this was in the old wimschem a faulty smiles interpretation...)
  725.         line 5 : latex formula  : eg C_{5}H_{4}O_{2}
  726.     */
  727.     public String ReadApplet(){
  728.         try{
  729.             StringWriter sw = new StringWriter();
  730.             BufferedWriter bw = new BufferedWriter(sw);
  731.             MoleculeStream.writeNative(bw,mainPanel.molData());
  732.             String nativemol = sw.toString();
  733.             nativemol = nativemol.replaceAll(" ","");
  734.             return moleculeData(nativemol);
  735.         }catch(Exception e){return e.toString();}
  736.     }
  737.    
  738.     public String moleculeData(String S){
  739.         int N=Molecule.ELEMENTS.length;
  740.         double[] WEIGHTS={0.0,1.00794,4.002602,6.941,9.01218,10.811,12.011,14.00674,15.9994,18.998403,20.1797,
  741.         22.989768,24.305,26.981539,28.0855,30.973762,32.066,35.4527,39.948,39.0983,40.078,
  742.         44.95591,47.88,50.9415,51.9961,54.93805,55.847,58.9332,58.6934,63.546,65.39,
  743.         69.723,72.61,74.92159,78.96,79.904,83.8,85.4678,87.62,88.90585,91.224,
  744.         92.90638,95.94,97.9072,101.07,102.9055,106.42,107.8682,112.411,114.818,118.71,
  745.         121.760,127.6,126.90447,131.29,132.90543,137.327,138.9055,140.115,140.90765,144.24,
  746.         144.9127,150.36,151.965,157.25,158.92534,162.50,164.93032,167.26,168.93421,173.04,
  747.         174.967,178.49,180.9479,183.84,186.207,190.23,192.22,195.08,196.96654,200.59,
  748.         204.3833,207.2,208.98037,208.9824,209.9871,222.0176,223.0197,226.0254,227.0278,232.0381,
  749.         231.03588,238.0289,237.048,244.0642,243.0614,247.0703,247.0703,251.0796,252.083,257.0951,
  750.         258.1,259.1009,262.11};
  751.        
  752.         String[] s=S.split("\n");String[] atom;int s1=s[0].indexOf('(');int s2=s[0].indexOf(',');int s3=s[0].indexOf(')');
  753.         int n_s=Integer.parseInt(s[0].substring(s1+1,s2).trim());int b_s=Integer.parseInt(s[0].substring(s2+1,s3).trim());
  754.         String[] E_s=new String[n_s];int[] H_s=new int[n_s];int[] C_s=new int[n_s];int[] R_s=new int[n_s];
  755.         int[] this_A=new int[N];int[] this_C=new int[N];int[] this_R=new int[N];int[] this_H=new int[N];
  756.         String plainformula="";String htmlformula="";String latexformula="";
  757.         String R_plain="";String R_html="";String R_latex="";
  758.         String C_plain="";String C_html="";String C_latex="";
  759.         String sign;
  760.         double weight_s=0.0D;int r=0;
  761.        
  762.         /* loop only through the atom part of the file-string */
  763.         for( int p=0; p<n_s ;p++){
  764.             atom=s[p+1].split("[\\=\\,\\;]"); /* first line is mimetype */
  765.             E_s[p]=atom[0];r=0;
  766.             for(int n=0;n<N;n++){
  767.                 if(atom[0].equals(Molecule.ELEMENTS[n])){
  768.                     weight_s=(double)(weight_s + WEIGHTS[n]);
  769.                     this_A[n]++;r=n;n=N;
  770.                 }
  771.             }
  772.             C_s[p]=Integer.parseInt(atom[3]);
  773.             this_C[r]=C_s[p];
  774.             R_s[p]=Integer.parseInt(atom[4]);
  775.             this_R[p]=R_s[p];
  776.             if( atom[5].indexOf("i")!=-1){
  777.                 atom[5]=atom[5].replaceAll("i","");H_s[p]=Integer.parseInt(atom[5]);this_H[r]=H_s[p];this_A[1]=this_A[1]+H_s[p];//hydrogen
  778.             }
  779.             else
  780.             {
  781.                 atom[5]=atom[5].replaceAll("e","");H_s[p]=Integer.parseInt(atom[5]);this_H[r]=H_s[p];this_A[1]=this_A[1]+H_s[p];//hydrogen
  782.             }      
  783.             weight_s=(double)(weight_s + H_s[p]);
  784.         }
  785.  
  786.         if(this_A[6]!=0){
  787.             if(this_R[6] != 0){R_plain="\u2022";R_latex="^{^{\\cdot}}";R_html="<sup>&cdot;</sup>";}
  788.             if(this_C[6] != 0){
  789.                 if(this_C[6]>0){sign="+";}else{sign="-";this_C[6]=(int) (Math.abs(this_C[6]));}
  790.                 C_plain=this_C[6]+sign;C_latex="^{"+this_C[6]+sign+"}";C_html="<sup><small>"+this_C[6]+sign+"</small></sup>";
  791.             }
  792.             if(this_A[6] == 1 ){/* C1 is not done:  CH4 */
  793.                 plainformula="C"+C_plain+R_plain+" ";
  794.                 htmlformula="<span style=\"fontsize:110%\" ><tt>C"+C_html+R_html+"</tt></span>";
  795.                 latexformula="\\Bf{C"+C_latex+R_latex+"}";
  796.             }
  797.             else
  798.             {//C2H5OH
  799.                 plainformula="C"+C_plain+R_plain+this_A[6];
  800.                 htmlformula="<span style=\"fontsize:110%\" ><tt>C"+C_html+R_html+"</tt></span><sub><small>"+this_A[6]+"</small></sub>";
  801.                 latexformula="\\Bf{C"+C_latex+R_latex+"}_{"+this_A[6]+"}";
  802.             }
  803.         }
  804.         // the rest
  805.         for(int p = 0; p<N; p++){
  806.             if( p == 6 ){ p = 7;} /* we already covered carbon */
  807.             if( this_A[p] != 0 ){
  808.                 R_plain="";R_html="";R_latex="";C_plain="";C_html="";C_latex="";sign="";
  809.                 if( this_R[p] != 0 ){ R_plain=this_R[p]+"\u2022";R_latex="^{^{"+this_R[p]+"\\cdot}}";R_html="<sup><sup>"+this_R[p]+"&cdot;</sup></sup>";}
  810.                 if( this_C[p] != 0 ){ if( this_C[p]>0 ){ sign="+"; } else { sign="-"; this_C[p]=-1*this_C[p];}C_plain=this_C[p]+sign;C_latex="^{"+this_C[p]+sign+"}";C_html="<sup><small>"+this_C[p]+sign+"</small></sup>";}
  811.                 if( this_A[p] == 1 ){
  812.                     plainformula=plainformula+" "+Molecule.ELEMENTS[p]+""+C_plain+""+R_plain;
  813.                     htmlformula=htmlformula+" <span style=\"fontsize:110%\" ><tt>"+Molecule.ELEMENTS[p]+C_html+R_html+"</tt></span>";
  814.                     latexformula=latexformula+"\\,\\Bf{"+Molecule.ELEMENTS[p]+C_latex+R_latex+"}";
  815.                 }
  816.                 else
  817.                 {
  818.                     plainformula=plainformula+" "+Molecule.ELEMENTS[p]+""+C_plain+""+R_plain+""+this_A[p];
  819.                     htmlformula=htmlformula+" <span style=\"fontsize:110%\" ><tt>"+Molecule.ELEMENTS[p]+C_html+R_html+"</tt></span><sub><small>"+this_A[p]+"</small></sub>";
  820.                     latexformula=latexformula+"\\,\\Bf{"+Molecule.ELEMENTS[p]+C_latex+R_latex+"}_{"+this_A[p]+"}";
  821.                 }
  822.             }
  823.         }
  824.         DecimalFormat df = new DecimalFormat("#.#",new DecimalFormatSymbols(Locale.US));
  825.         /*
  826.             the second 'plainformula' was (the no good) previous smiles-formula ;
  827.             added just to satisfy my checkfiles ...
  828.         */
  829.         return df.format(weight_s)+"\n"+plainformula+"\n"+htmlformula+"\n"+plainformula+"\n"+latexformula;
  830.     }
  831. }
  832.