Subversion Repositories wimsdev

Rev

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