From: <ha...@us...> - 2011-08-01 14:12:34
|
Revision: 15901 http://jmol.svn.sourceforge.net/jmol/?rev=15901&view=rev Author: hansonr Date: 2011-08-01 14:12:27 +0000 (Mon, 01 Aug 2011) Log Message: ----------- ChimeToJmol Java program automatically changes web site from Chime to Jmol. First test Modified Paths: -------------- trunk/Jmol/src/org/openscience/chimetojmol/ChimePanel.java Added Paths: ----------- trunk/Jmol/src/org/openscience/chimetojmol/ChimeToJmol.js trunk/Jmol/src/org/openscience/chimetojmol/chimebtn16.png Modified: trunk/Jmol/src/org/openscience/chimetojmol/ChimePanel.java =================================================================== --- trunk/Jmol/src/org/openscience/chimetojmol/ChimePanel.java 2011-08-01 11:12:18 UTC (rev 15900) +++ trunk/Jmol/src/org/openscience/chimetojmol/ChimePanel.java 2011-08-01 14:12:27 UTC (rev 15901) @@ -32,17 +32,27 @@ public class ChimePanel extends JPanel implements ItemListener, ActionListener { private JTextField chimePath; - private Checkbox checkSubs; - private boolean doSubs; private JButton goButton, browseButton; private JTextArea logArea; private JScrollPane logScrollPane; private JFileChooser chooser; + private File oldDir; + private List<File> pages; + private int nDir; + private int nFiles; + private int nControls; + private Checkbox checkSubs, checkFilenames, checkSigned; + private boolean doSubdirectories; + private boolean doFixFilenames; + private boolean doUseSigned; + private File myDir; + ChimePanel() { chooser = new JFileChooser(); chooser.setCurrentDirectory(new File(".")); + myDir = chooser.getCurrentDirectory(); chooser.setDialogTitle("Select a Directory"); chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); chooser.setAcceptAllFileFilterUsed(false); @@ -51,7 +61,7 @@ chimePath = new JTextField(50); chimePath.addActionListener(this); - chimePath.setText("c:/temp/teaching"); + chimePath.setText("c:/temp/Teaching"); JPanel pathPanel = new JPanel(); pathPanel.setLayout(new BorderLayout()); @@ -64,9 +74,18 @@ pathPanel.add("East", browseButton); add("North", pathPanel); + JPanel checkPanel = new JPanel(); + checkPanel.setLayout(new BorderLayout()); checkSubs = new Checkbox("include subdirectories"); checkSubs.addItemListener(this); - add("Center", checkSubs); + checkFilenames = new Checkbox("fix file name case"); + checkFilenames.addItemListener(this); + checkSigned = new Checkbox("use signed applet"); + checkSigned.addItemListener(this); + checkPanel.add("North", checkSubs); + checkPanel.add("Center", checkSigned); + checkPanel.add("South", checkFilenames); + add("Center", checkPanel); JPanel lowerPanel = new JPanel(); lowerPanel.setLayout(new BorderLayout()); @@ -81,7 +100,7 @@ logArea.setMargin(new Insets(5, 5, 5, 5)); logArea.setEditable(false); logScrollPane = new JScrollPane(logArea); - logScrollPane.setBorder(BorderFactory.createTitledBorder("0 files")); + logScrollPane.setBorder(BorderFactory.createTitledBorder("0 pages")); lowerPanel.add("South", logScrollPane); @@ -102,30 +121,33 @@ Object source = e.getSource(); int stateChange = e.getStateChange(); if (source == checkSubs) { - doSubs = (stateChange == ItemEvent.SELECTED); + doSubdirectories = (stateChange == ItemEvent.SELECTED); getFileList(); } + if (source == checkFilenames) { + doFixFilenames = (stateChange == ItemEvent.SELECTED); + } + if (source == checkSigned) { + doUseSigned = (stateChange == ItemEvent.SELECTED); + } } private void log(String string) { logArea.setText(logArea.getText() + string + "\n"); } - private String oldDir; - private List<File> files; - void getFileList() { logArea.setText(""); - files = new ArrayList<File>(); + pages = new ArrayList<File>(); String dir = chimePath.getText(); dir = dir.replace('\\', '/'); while (dir.endsWith("/")) dir = dir.substring(0, dir.length() - 1); if (dir.length() < 4) return; - oldDir = dir; + oldDir = new File(dir); try { - copyDirectory("", new File(oldDir), new File(oldDir + "_jmol"), true); + copyDirectory("", oldDir, new File(oldDir + "_jmol"), true); } catch (IOException e) { log(e.getMessage()); } @@ -134,7 +156,7 @@ private void doGo() { logArea.setText(""); try { - copyDirectory("", new File(oldDir), new File(oldDir + "_jmol"), false); + copyDirectory("", oldDir, new File(oldDir + "_jmol"), false); } catch (IOException e) { logArea.setText(e.getMessage()); } @@ -148,15 +170,28 @@ } } - public void copyDirectory(String level, File sourceLocation, - File targetLocation, boolean justChecking) + private String rootDir; + + private void copyDirectory(String level, File sourceLocation, + File targetLocation, boolean justChecking) throws IOException { - + if (level.equals("")) { + nDir = nFiles = 0; + rootDir = targetLocation.getAbsolutePath(); + if (!justChecking) { + deleteDirectory(targetLocation); + targetLocation.mkdir(); + addJmolFiles(rootDir); + } + } else if (doFixFilenames) { + targetLocation = new File(fixFileName(targetLocation)); + } if (sourceLocation.isDirectory()) { - if (!doSubs && !level.equals("")) + if (!doSubdirectories && !level.equals("")) return; - if (!targetLocation.exists() && !justChecking) - targetLocation.mkdir(); + nDir++; + if (!targetLocation.exists() && !justChecking) + targetLocation.mkdir(); String[] children = sourceLocation.list(); for (int i = 0; i < children.length; i++) copyDirectory((level.equals("") ? "." : level.equals(".") ? ".." @@ -165,23 +200,84 @@ } else { if (!copyFile(level, sourceLocation, targetLocation, justChecking)) log("Hmm..." + sourceLocation + " --> " + targetLocation); + nFiles++; } + showProgress(); } + private void addJmolFiles(String rootDir) { + File dir = myDir; + if (! new File(dir, "Jmol.js").exists()) + dir = oldDir; + File dest = new File(rootDir); + + String[] list = dir.list(); + for (int i = 0; i < list.length; i++) { + String f = list[i]; + if (!f.equals("Jmol.js") + && !f.equals("ChimeToJmol.js") + && !f.startsWith("chimebtn")) { + if (!f.startsWith("JmolApplet") || !f.endsWith(".jar") + || doUseSigned != (f.indexOf("AppletSigned") >= 0)) + continue; + } + justTransferFile(new File(dir, f), new File(dest, f)); + } + } + + public static boolean deleteDirectory(File directory) { + if (directory == null) + return false; + if (!directory.exists()) + return true; + if (!directory.isDirectory()) + return false; + String[] list = directory.list(); + if (list != null) { + for (int i = 0; i < list.length; i++) { + File entry = new File(directory, list[i]); + if (entry.isDirectory()) { + if (!deleteDirectory(entry)) + return false; + } else { + if (!entry.delete()) + return false; + } + } + } + return directory.delete(); + } + private String fixFileName(File f) { + return (rootDir + "/" + f.getAbsolutePath().substring(rootDir.length()).toLowerCase()).replace('\\','/'); + } + + private void showProgress() { + String s = pages.size() + " pages/" + + (nDir > 1 ? nDir + " directories/" : "") + nFiles + " files"; + logScrollPane.setBorder(BorderFactory.createTitledBorder(s)); + } + private boolean copyFile(String level, File f1, File f2, boolean justChecking) { - if (f1.getName().endsWith(".htm") || f1.getName().endsWith(".html")) { + String name = f1.getName().toLowerCase(); + if (name.endsWith(".htm") || name.endsWith(".html")) { if (justChecking) { - files.add(f1); + pages.add(f1); log(f1.getAbsolutePath()); - logScrollPane.setBorder(BorderFactory.createTitledBorder(files.size() - + " files")); return true; } - log(f1.getAbsolutePath() + " --> " + f2.getAbsolutePath()); - return processFile(level, f1, f2); - } + log("---\n" + f1.getAbsolutePath() + " --> " + f2.getAbsolutePath()); + return processFile(level, f1, f2, true, true); + } if (justChecking) return true; + if (name.endsWith(".spt")) { + log("---\n" + f1.getAbsolutePath() + " --> " + f2.getAbsolutePath()); + return processFile(level, f1, f2, false, true); + } + return justTransferFile(f1, f2); + } + + private boolean justTransferFile(File f1, File f2) { try { InputStream in = new FileInputStream(f1); OutputStream out = new FileOutputStream(f2); @@ -202,33 +298,115 @@ private static Pattern embed1 = Pattern.compile("<embed", Pattern.CASE_INSENSITIVE); private static Pattern embed2 = Pattern.compile("</embed", Pattern.CASE_INSENSITIVE); - private boolean processFile(String level, File f1, File f2) { - String html = getFileContents(f1); - if (html == null) { + private boolean processFile(String level, File f1, File f2, + boolean processHtml, boolean processChime) { + String data = getFileContents(f1); + if (data == null) { log("?error reading " + f1.getAbsolutePath()); return false; } - if (html.indexOf("Jmol.js") < 0) { + if (doFixFilenames) + data = fixFileNames(data, processHtml); + if (processHtml && data.indexOf("Jmol.js") < 0) { String opener = "\n<script type=\"text/javascript\""; String s = opener + " src=\"" + level + "/Jmol.js\"></script>"; - s += opener + ">jmolInitialize('" + level + "')</script>"; s += opener + " src=\"" + level + "/ChimeToJmol.js\"></script>"; - int i = html.toLowerCase().indexOf("<head>"); + s += opener + ">jmolInitialize('" + level + "'," + doUseSigned + ");chimebtn = '" + level + + "/chimebtn16.png';</script>"; + int i = data.toLowerCase().indexOf("<head>"); if (i < 0) { - html = "<head></head>" + html; + data = "<head></head>" + data; i = 0; } - html = html.substring(0, i + 6) + s + "\n" + html.substring(i + 6); - html = embed1.matcher(html).replaceAll("<xembed"); - html = embed2.matcher(html).replaceAll("</xembed"); + data = data.substring(0, i + 6) + s + "\n" + data.substring(i + 6); + data = embed1.matcher(data).replaceAll("<xembed"); + data = embed2.matcher(data).replaceAll("</xembed"); } - if (!putFileContents(f2, html)) { + if (processChime) { + data = fixChime(data, processHtml); + } + if (!putFileContents(f2, data)) { log("?error creating " + f2); return false; } return true; } + private String fixFileNames(String data, boolean isHtml) { + if (isHtml) { + data = fixFileNames(data, "src=", '\0'); + data = fixFileNames(data, "script=", '\0'); + } + if (data.startsWith("load")) + data = "\n" + data + "\n"; + data = fixFileNames(data, "\nload", '\n'); + return data; + } + + private String fixFileNames(String data, String what, char term) { + int i = -1; + boolean isScript = what.equals("script="); + String lcdata = data.toLowerCase(); + StringBuffer dataOut = new StringBuffer(); + int pt0 = 0; + int i1 = 0; + while ((i = lcdata.indexOf(what, i + 1)) >= 0) { + if (term == '\n') { + i1 = data.indexOf(term, i + 1); + } else { + i1 = i + what.length(); + if (i1 == data.length()) + break; + boolean stopDQuote = data.charAt(i1) == '"'; + boolean stopSQuote = data.charAt(i1) == '\''; + boolean stopSpace = (!stopDQuote && !stopSQuote); + if (stopDQuote || stopSQuote) + i1++; + if (stopSpace) + while(i1 < data.length() && Character.isWhitespace(data.charAt(i1))) + i1++; + out: for (; i1 < data.length(); i1++) { + if (stopSpace && Character.isWhitespace(data.charAt(i1))) + break; + switch (data.charAt(i1)) { + case '"': + if (stopDQuote) + break out; + break; + case '\'': + if (stopSQuote) + break out; + break; + case '>': + break out; + } + } + } + String s; + if (isScript) { + // slight potential for error here when ; is quoted + s = fixFileNames(data.substring(i, i1).replace(';','\n'), false).replace('\n', ';'); + } else { + s = lcdata.substring(i, i1); + } + log(data.substring(i, i1) + " --> " + s); + dataOut.append(data.substring(pt0, i)).append(s); + pt0 = i1; + } + dataOut.append(data.substring(pt0, data.length())); + return dataOut.toString(); + } + + /** + * @param data + * @param isHtml + * @return fixed Chime commands + */ + private String fixChime(String data, boolean isHtml) { + // (JavaScript will do this) + return data; + } + private String getFileContents(File f) { StringBuffer sb = new StringBuffer(8192); String line; Added: trunk/Jmol/src/org/openscience/chimetojmol/ChimeToJmol.js =================================================================== --- trunk/Jmol/src/org/openscience/chimetojmol/ChimeToJmol.js (rev 0) +++ trunk/Jmol/src/org/openscience/chimetojmol/ChimeToJmol.js 2011-08-01 14:12:27 UTC (rev 15901) @@ -0,0 +1,261 @@ +/* + +ChimeToJmol.js +ha...@st... 8:07 AM 4/21/2010 +# last update 10/18/2010 7:24:31 AM (comments added 12:35 PM 4/13/2011) + +A set of functions that will (when fully developed) +allow just about any Chime page to be converted automatically +from Chime EMBED tags to Jmol applets and buttons. + +Also changes older Jmol "applet" code to use Jmol.js + +1) Set jmolDirectory (below) to the desired directory to contain + the standard Jmol files (Jmol.js, JmolApplet*.jar) + as well as this file, ChimeToJmol.js + and add those files to it. + +2) add these lines to your page's <HEAD> section (with the appropriate directory, if needed): + + <script language="javascript" SRC="Jmol.js"> </script> + <script language="javascript" SRC="ChimeToJmol.js"> </script> + +3) using a multi-file text editor such as superFix.exe + (http://stolaf.edu/people/hansonr/origami/WIN/SUPERFIX.EXE) + change allow occurances of "<EMBED" to "<xembed" + +4) If you are using a BODY onload="funcName()" attribute already, +then add + + checkJmol() + +to it. + +5) If you want to test your page, add "?NOJMOL" to the page URL + +TODO: more script conversions needed for Chime + + +*/ + +// set this as desired +var jmolDirectory = "." +var useSignedApplet = false // still, always uses signed applet for LOCAL testing +var chimebtn = "" + +//jmolDebugAlert() + + +// You will probably have to adjust this next function +// to include more cases. These are just an example of the sort +// of fixes that need to be done to convert Chime scripts to Jmol scripts + +function __jmolFixChimeScript(script) { + script = "set defaultLoadScript 'wireframe only;rotate x 180;';" + + script + //.replace(/\*\./g,"_") // as in *.C, *.H, for some small-molecular installations + .replace(/stick on/g,"wireframe 0.15;") + .replace(/ball\&\;stick off/g,"wireframe off;spacefill off") + .replace(/select startanim\=false/g,"animation off") + .replace(/select startanim\=true/g,"animation play") + .replace(/set cartoon/g,"#set cartoon") + .replace(/set dots/g,"#set dots") + .replace(/reset/g,"reset;rotate x 180") + .replace(/rotate z\s+/g,"rotate z -") + .replace(/ --/g," ") + .replace(/set shadow/g,"#set shadow") + return script +} + +function __jmolGenericCallback(a, b, c, d, e) { + b || (b = "") + c || (c = "") + d || (d = "") + e || (e = "") + alert([a, b, c, d, e].join("\n\n")) +} + +/////////Jmol section ////////// + +function checkJmol() { + if (top.location.search.indexOf("NOJMOL") >= 0)return + var body = document.body.innerHTML + if (body.indexOf("JmolApplet") >= 0) { + if(body.indexOf("JmolAppletControl") >= 0)__fixJmol() + return + } + if (body.indexOf("<xembed") >= 0 || body.indexOf("<xembed") >= 0) __fixChime() +} + +window.onload = checkJmol + +function __fixJmol() { + var body = document.body.innerHTML + var ptAPPLET = -1 + var Text = body.split("<applet") + if (Text.length == 1)return + for (var i = 1; i < Text.length; i++) { + var text = Text[i] + var pt = text.indexOf("</applet>") + if (text.indexOf("JmolAppletControl") >= 0) { + Text[i] = __jmolFixJmolAppletControl(text.substring(0, pt)) + text.substring(pt + 9) + } else if (text.indexOf("JmolApplet") >= 0) { + Text[i] = __jmolFixJmolApplet(text.substring(0, pt)) + text.substring(pt + 9) + } else { + Text[i] = "<applet" + text + continue + } + } + document.body.innerHTML = Text.join("") +} + +function __jmolFixJmolApplet(tag) { + var A = __jmolGetAttributes(tag) + if (!A.width)A.width = 300 + if (!A.height)A.height = 300 + if (!A.script)A.script = "" + if (!A.codebase)A.codebase = jmolDirectory + if (A.archive == "JmolApplet.jar") A.archive = "JmolApplet0.jar" + if (document.location.protocol == "file:" && A.archive.indexOf("Signed") < 0) A.archive = "JmolAppletSigned0.jar" + if (A.load)A.script = "load \"" + A.load + "\";" + A.script + jmolInitialize(A.codebase, A.archive) + jmolSetDocument(0) + return jmolApplet([A.width,A.height],A.script, A.name) +} + +function __jmolFixJmolAppletControl(tag) { + var A = __jmolGetAttributes(tag) + if (!A.width)A.width = 12 + if (!A.height)A.height = 12 + _jmol.buttonCssText = "style=\"width:" + A.width + "\"" + if (A.altscript) + return jmolCheckbox(A.script, A.altscript, "", false, A.target) + return "<span width=\"" + A.width + "\" height=\"" + A.height + "\">" + jmolButton(A.script,"X",A.target) + "</span>" +} + +function __fixChime() { + jmolInitialize(jmolDirectory, + (document.location.protocol=="file:" || useSignedApplet ? "JmolAppletSigned0.jar" : "JmolApplet0.jar")) + jmolSetDocument(0) + var body = document.body.innerHTML + var Text = body.split("<xembed") + if (Text.length == 1)Text = body.split("<xembed") + if (Text.length == 1)return + + for (var i = 1; i < Text.length; i++) { + var text = Text[i] + var iq = 0; + var pt = 0; + for (; pt < text.length && iq >= 0;pt++) { + switch (text.charAt(pt)) { + case '"': + case "'": + iq += 1 + break + case '>': + if (iq%2==0) { + iq = -1 + } + } + if (iq < 0) + break; + } + var isButton = (text.indexOf("target=") >= 0) + if (isButton) { + Text[i] = __jmolFixChimeButton(text.substring(0, pt), i) + text.substring(pt + 1) + } else { + Text[i] = __jmolFixChimeApplet(text.substring(0, pt)) + text.substring(pt + 1) + } + } + document.body.innerHTML = Text.join("") +} + +function __jmolFixChimeApplet(tag) { + var A = __jmolGetAttributes(tag) + if (A.width.indexOf("%") < 0) + A.width = parseInt(A.width) + if (A.height.indexOf("%") < 0) + A.height = parseInt(A.height) + A.script = (A.script ? __jmolFixChimeScript(A.script) : "") + if (A.animmode) A.script += ";animation mode " + A.animmode + ";" + if (A.animfps) A.script += ";animation fps " + A.animfps + ";" + if (A.startanim && A.startanim.toLowerCase() == "true") A.script += ";animation on;" + if (A.src.indexOf(".spt")>= 0) { + A.src = 'chimeScript = load("' + A.src + '"); javascript "__jmolRunChimeScript(\''+A.name+'\')";' + } else { + A.src = "load = \"" + A.src + "\";" + } + if (A.name) + jmolSetTarget(A.name) + var s = jmolApplet([A.width,A.height],A.src + A.script + ";set errorCallback '__jmolGenericCallback'", A.name) + return s +} + +function __jmolRunChimeScript(target) { + var script = jmolEvaluate('chimeScript', target) + script = __jmolFixChimeScript(script) + jmolScript(script, target); +} + +function __jmolFixChimeButton(tag, iBtn) { + var A = __jmolGetAttributes(tag, iBtn) + if (!A.width)A.width = 12 + if (!A.height)A.height = 12 + if (A.src) { + A.script = 'chimeScript = load("' + A.src + '"); javascript "__jmolRunChimeScript(\''+A.target+'\')"' + } else { + A.script = __jmolFixChimeScript(A.script) + } + jmolSetTarget(A.target) + var text = (chimebtn ? "<img border='none' src='"+chimebtn+"'>" : "[x]") + var s = "<span width=\"" + A.width + "\" height=\"" + A.height + "\">" + jmolLink(A.script,text, Math.random(), A.script.replace(/\"/g,"'")) + " </span>" + return s +} + +function __jmolGetAttributes(tag, iBtn) { + var S = {} + var name = "" + var value = "" + var inName = false + var inValue = false + tag = tag.replace(/\<br\>/g, " ") + tag = tag.replace(/\<br \/\>/g, " ") + if (tag.substring(tag.length-1, tag.length) == "/") + tag = tag.substring(0, tag.length-1) + if (tag.indexOf("<param") >= 0) + tag = tag.replace(/\<param name\=/g," ") + .replace(/value\=/g,"=") + .replace(/\/\>/g, " ") + .replace(/\>/g, " ") + tag = tag.replace(/\s+/g, " ") + tag = tag.replace(/ \=/g, "=") + tag = tag.replace(/\= /g, "=") + tag += " =" + for (var i = 0; i < tag.length - 2; i++) { + if (tag.charAt(i) == " ") + continue + var pts = tag.indexOf(" ", i) + var pte = tag.indexOf("=", i) + var ptq = tag.indexOf("'", pte + 1) + var ptqq = tag.indexOf("\"", pte + 1) + if (ptqq == pte + 1)ptq = ptqq + var ptq2 = tag.indexOf((ptq == ptqq ? "\"" : "'"), ptq + 1) + if (pts < pte) { + // <xembed xxxx ... + S[tag.substring(i, pts).toLowerCase().replace(/[\'\"]/g,"")] = "" + i = pts + } else if (pts < ptq || ptq < 0) { + // <xembed xxxx=yyy ... + S[tag.substring(i, pte).toLowerCase().replace(/[\'\"]/g,"")] = tag.substring(pte + 1, pts) + i = pts + } else { + // <xembed xxxx="yyy" ... + S[tag.substring(i, pte).toLowerCase().replace(/[\'\"]/g,"")] = tag.substring(ptq + 1, ptq2) + i = ptq2 + } + if (i < 0){quit} + } + return S +} + + Added: trunk/Jmol/src/org/openscience/chimetojmol/chimebtn16.png =================================================================== (Binary files differ) Property changes on: trunk/Jmol/src/org/openscience/chimetojmol/chimebtn16.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |