1 /* $RCSfile$ 2 * $Author: hansonr $ 3 * $Date: 2010-05-11 15:47:18 -0500 (Tue, 11 May 2010) $ 4 * $Revision: 13064 $ 5 * 6 * Copyright (C) 2000-2005 The Jmol Development Team 7 * 8 * Contact: jmol-developers@lists.sf.net 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 23 */ 24 package org.jmol.popup; 25 26 import java.util.Arrays; 27 import java.util.Hashtable; 28 import java.util.Map; 29 30 import org.jmol.api.SC; 31 import org.jmol.i18n.GT; 32 import org.jmol.i18n.Language; 33 import org.jmol.modelset.Group; 34 import org.jmol.script.T; 35 import org.jmol.util.Elements; 36 import org.jmol.viewer.JC; 37 38 import javajs.util.BS; 39 import javajs.util.Lst; 40 import javajs.util.PT; 41 42 /** 43 * An abstract popup class that is 44 * instantiated for a given platform and 45 * context as one of: 46 * 47 * <pre> 48 * -- abstract JmolPopup 49 * -- AwtJmolPopup 50 * -- JSJmolPopup 51 * </pre> 52 * 53 */ 54 abstract public class JmolPopup extends JmolGenericPopup { 55 56 //list is saved in http://www.stolaf.edu/academics/chemapps/jmol/docs/misc 57 58 protected final static int UPDATE_NEVER = -1; 59 protected final static int UPDATE_ALL = 0; 60 protected final static int UPDATE_CONFIG = 1; 61 protected final static int UPDATE_SHOW = 2; 62 63 //public void finalize() { 64 // Sygstem.out.println("JmolPopup " + this + " finalize"); 65 //} 66 67 protected int updateMode = UPDATE_ALL; 68 69 private static final int itemMax = 25; 70 private int titleWidthMax = 20; 71 private String nullModelSetName, modelSetName; 72 private String modelSetFileName, modelSetRoot; 73 private String currentFrankId = null; 74 private String configurationSelected = ""; 75 private String altlocs; 76 77 private Object[][] frankList = new Object[10][]; //enough to cover menu drilling 78 79 private Map<String, Object> modelSetInfo; 80 protected Map<String, Object> modelInfo; 81 82 private Lst<SC> NotPDB = new Lst<SC>(); 83 private Lst<SC> PDBOnly = new Lst<SC>(); 84 private Lst<SC> FileUnitOnly = new Lst<SC>(); 85 private Lst<SC> FileMolOnly = new Lst<SC>(); 86 private Lst<SC> UnitcellOnly = new Lst<SC>(); 87 private Lst<SC> SingleModelOnly = new Lst<SC>(); 88 private Lst<SC> FramesOnly = new Lst<SC>(); 89 private Lst<SC> VibrationOnly = new Lst<SC>(); 90 protected Lst<SC> Special = new Lst<SC>(); 91 private Lst<SC> SymmetryOnly = new Lst<SC>(); 92 private Lst<SC> ChargesOnly = new Lst<SC>(); 93 private Lst<SC> TemperatureOnly = new Lst<SC>(); 94 95 private boolean fileHasUnitCell; 96 private boolean haveBFactors; 97 private boolean haveCharges; 98 private boolean isLastFrame; 99 private boolean isMultiConfiguration; 100 private boolean isMultiFrame; 101 private boolean isPDB; 102 private boolean hasSymmetry; 103 private boolean isUnitCell; 104 private boolean isVibration; 105 private boolean isZapped; 106 107 protected int modelIndex; 108 private int modelCount; 109 private int ac; 110 111 private String group3List; 112 private int[] group3Counts; 113 private Lst<String> cnmrPeaks; 114 private Lst<String> hnmrPeaks; 115 116 ////// JmolPopupInterface methods ////// 117 118 private final static int MENUITEM_HEIGHT = 20; 119 120 @Override jpiDispose()121 public void jpiDispose() { 122 super.jpiDispose(); 123 helper.menuClearListeners(frankPopup); 124 frankPopup = null; 125 } 126 127 @Override getBundle(String menu)128 protected PopupResource getBundle(String menu) { 129 return new MainPopupResourceBundle(strMenuStructure = menu, 130 menuText); 131 } 132 133 134 @Override showFrankMenu()135 protected boolean showFrankMenu() { 136 // frank has been clicked 137 getViewerData(); 138 setFrankMenu(currentMenuItemId); 139 thisx = -thisx - 50; 140 if (nFrankList > 1) { 141 thisy -= nFrankList * MENUITEM_HEIGHT; 142 menuShowPopup(frankPopup, thisx, thisy); 143 return false; 144 } 145 return true; 146 } 147 148 @Override jpiUpdateComputedMenus()149 public void jpiUpdateComputedMenus() { 150 if (updateMode == UPDATE_NEVER) 151 return; 152 isTainted = true; 153 getViewerData(); 154 updateMode = UPDATE_ALL; 155 updateMenus(); 156 } 157 158 ///////// protected methods ////////// 159 160 @SuppressWarnings("unchecked") updateMenus()161 protected void updateMenus() { 162 updateSelectMenu(); 163 updateModelSetComputedMenu(); 164 updateAboutSubmenu(); 165 if (updateMode == UPDATE_ALL) { 166 updateFileMenu(); 167 updateElementsComputedMenu(vwr.getElementsPresentBitSet(modelIndex)); 168 updateHeteroComputedMenu(vwr.ms.getHeteroList(modelIndex)); 169 updateSurfMoComputedMenu((Map<String, Object>) modelInfo.get("moData")); 170 updateFileTypeDependentMenus(); 171 updatePDBResidueComputedMenus(); 172 updateMode = UPDATE_CONFIG; 173 updateConfigurationComputedMenu(); 174 updateSYMMETRYComputedMenus(); 175 updateFRAMESbyModelComputedMenu(); 176 updateLanguageSubmenu(); 177 } else { 178 updateSpectraMenu(); 179 updateFRAMESbyModelComputedMenu(); 180 updateSceneComputedMenu(); 181 for (int i = Special.size(); --i >= 0;) 182 updateSpecialMenuItem(Special.get(i)); 183 } 184 } 185 186 @Override appCheckItem(String item, SC newMenu)187 protected void appCheckItem(String item, SC newMenu) { 188 if (item.indexOf("!PDB") >= 0) { 189 NotPDB.addLast(newMenu); 190 } else if (item.indexOf("PDB") >= 0) { 191 PDBOnly.addLast(newMenu); 192 } 193 if (item.indexOf("CHARGE") >= 0) { 194 ChargesOnly.addLast(newMenu); 195 } else if (item.indexOf("BFACTORS") >= 0) { 196 TemperatureOnly.addLast(newMenu); 197 } else if (item.indexOf("UNITCELL") >= 0) { 198 UnitcellOnly.addLast(newMenu); 199 } else if (item.indexOf("FILEUNIT") >= 0) { 200 FileUnitOnly.addLast(newMenu); 201 } else if (item.indexOf("FILEMOL") >= 0) { 202 FileMolOnly.addLast(newMenu); 203 } 204 if (item.indexOf("!FRAMES") >= 0) { 205 SingleModelOnly.addLast(newMenu); 206 } else if (item.indexOf("FRAMES") >= 0) { 207 FramesOnly.addLast(newMenu); 208 } 209 if (item.indexOf("VIBRATION") >= 0) { 210 VibrationOnly.addLast(newMenu); 211 } else if (item.indexOf("SYMMETRY") >= 0) { 212 SymmetryOnly.addLast(newMenu); 213 } 214 if (item.indexOf("SPECIAL") >= 0) 215 Special.addLast(newMenu); 216 } 217 218 @Override appGetMenuAsString(String title)219 protected String appGetMenuAsString(String title) { 220 return (new MainPopupResourceBundle(strMenuStructure, null)) 221 .getMenuAsText(title); 222 } 223 224 @Override getScriptForCallback(SC source, String id, String script)225 protected String getScriptForCallback(SC source, String id, String script) { 226 int pt; 227 if (script == "" || id.endsWith("Checkbox")) 228 return script; 229 230 if (script.indexOf("SELECT") == 0) { 231 return "select thisModel and (" + script.substring(6) + ")"; 232 } 233 234 if ((pt = id.lastIndexOf("[")) >= 0) { 235 // setSpin 236 id = id.substring(pt + 1); 237 if ((pt = id.indexOf("]")) >= 0) 238 id = id.substring(0, pt); 239 id = id.replace('_', ' '); 240 if (script.indexOf("[]") < 0) 241 script = "[] " + script; 242 script = script.replace('_', ' '); 243 return PT.rep(script, "[]", id); 244 } else if (script.indexOf("?FILEROOT?") >= 0) { 245 script = PT.rep(script, "FILEROOT?", modelSetRoot); 246 } else if (script.indexOf("?FILE?") >= 0) { 247 script = PT.rep(script, "FILE?", modelSetFileName); 248 } else if (script.indexOf("?PdbId?") >= 0) { 249 script = PT.rep(script, "PdbId?", "=xxxx"); 250 } 251 return script; 252 } 253 254 @Override appRestorePopupMenu()255 protected void appRestorePopupMenu() { 256 thisPopup = popupMenu; 257 // JavaScript does not have to re-insert the menu 258 // because it never gets removed in the first place. 259 // first entry is just the main item 260 if (vwr.isJSNoAWT || nFrankList < 2) // TODO BOBJOB 261 return; 262 for (int i = nFrankList; --i > 0;) { 263 Object[] f = frankList[i]; 264 helper.menuInsertSubMenu((SC) f[0], (SC) f[1], 265 ((Integer) f[2]).intValue()); 266 } 267 nFrankList = 1; 268 } 269 270 /** 271 * (1) setOption --> set setOption true or set setOption false 272 * 273 * @param item 274 * 275 * @param what 276 * option to set 277 * @param TF 278 * true or false 279 */ 280 @Override appUpdateSpecialCheckBoxValue(SC item, String what, boolean TF)281 protected void appUpdateSpecialCheckBoxValue(SC item, String what, boolean TF) { 282 if (!updatingForShow && what.indexOf("#CONFIG") >= 0) { 283 configurationSelected = what; 284 updateConfigurationComputedMenu(); 285 updateModelSetComputedMenu(); 286 } 287 } 288 289 ///////// private methods ///////// 290 setFrankMenu(String id)291 private void setFrankMenu(String id) { 292 if (currentFrankId != null && currentFrankId == id && nFrankList > 0) 293 return; 294 if (frankPopup == null) 295 frankPopup = helper.menuCreatePopup("Frank", vwr.html5Applet); 296 // thisPopup is needed by the JavaScript side of the operation 297 thisPopup = frankPopup; 298 menuRemoveAll(frankPopup, 0); 299 menuCreateItem(frankPopup, getMenuText("mainMenuText"), "MAIN", ""); 300 currentFrankId = id; 301 nFrankList = 0; 302 frankList[nFrankList++] = new Object[] { null, null, null }; 303 if (id != null) 304 for (int i = id.indexOf(".", 2) + 1;;) { 305 int iNew = id.indexOf(".", i); 306 if (iNew < 0) 307 break; 308 SC menu = htMenus.get(id.substring(i, iNew)); 309 frankList[nFrankList++] = new Object[] { menu.getParent(), menu, 310 Integer.valueOf(vwr.isJSNoAWT ? 0 : menuGetListPosition(menu)) }; 311 menuAddSubMenu(frankPopup, menu); 312 i = iNew + 1; 313 } 314 thisPopup = popupMenu; 315 } 316 checkBoolean(String key)317 private boolean checkBoolean(String key) { 318 return (modelSetInfo != null && modelSetInfo.get(key) == Boolean.TRUE); // not "Boolean.TRUE.equals(...)" (not working in Java2Script yet) 319 } 320 321 @SuppressWarnings("unchecked") getViewerData()322 private void getViewerData() { 323 modelSetName = vwr.ms.modelSetName; 324 modelSetFileName = vwr.getModelSetFileName(); 325 int i = modelSetFileName.lastIndexOf("."); 326 isZapped = (JC.ZAP_TITLE.equals(modelSetName)); 327 if (isZapped || "string".equals(modelSetFileName) 328 || "String[]".equals(modelSetFileName)) 329 modelSetFileName = ""; 330 modelSetRoot = modelSetFileName.substring(0, 331 i < 0 ? modelSetFileName.length() : i); 332 if (modelSetRoot.length() == 0) 333 modelSetRoot = "Jmol"; 334 modelIndex = vwr.am.cmi; 335 modelCount = vwr.ms.mc; 336 ac = vwr.ms.getAtomCountInModel(modelIndex); 337 modelSetInfo = vwr.getModelSetAuxiliaryInfo(); 338 modelInfo = vwr.ms.getModelAuxiliaryInfo(modelIndex); 339 if (modelInfo == null) 340 modelInfo = new Hashtable<String, Object>(); 341 isPDB = checkBoolean("isPDB"); 342 isMultiFrame = (modelCount > 1); 343 hasSymmetry = modelInfo.containsKey("hasSymmetry"); 344 isUnitCell = modelInfo.containsKey("unitCellParams"); 345 fileHasUnitCell = (isPDB && isUnitCell || checkBoolean("fileHasUnitCell")); 346 isLastFrame = (modelIndex == modelCount - 1); 347 altlocs = vwr.ms.getAltLocListInModel(modelIndex); 348 isMultiConfiguration = (altlocs.length() > 0); 349 isVibration = (vwr.modelHasVibrationVectors(modelIndex)); 350 haveCharges = (vwr.ms.getPartialCharges() != null); 351 haveBFactors = (vwr.getBooleanProperty("haveBFactors")); 352 cnmrPeaks = (Lst<String>) modelInfo.get("jdxAtomSelect_13CNMR"); 353 hnmrPeaks = (Lst<String>) modelInfo.get("jdxAtomSelect_1HNMR"); 354 } 355 356 @Override appCheckSpecialMenu(String item, SC subMenu, String word)357 public void appCheckSpecialMenu(String item, SC subMenu, String word) { 358 // these will need tweaking: 359 if ("modelSetMenu".equals(item)) { 360 nullModelSetName = word; 361 menuEnable(subMenu, false); 362 } 363 } 364 365 @Override appUpdateForShow()366 protected void appUpdateForShow() { 367 if (updateMode == UPDATE_NEVER) 368 return; 369 isTainted = true; 370 getViewerData(); 371 updateMode = UPDATE_SHOW; 372 updateMenus(); 373 } 374 updateFileMenu()375 protected void updateFileMenu() { 376 SC menu = htMenus.get("fileMenu"); 377 if (menu == null) 378 return; 379 String text = getMenuText("writeFileTextVARIABLE"); 380 menu = htMenus.get("writeFileTextVARIABLE"); 381 if (menu == null) 382 return; 383 boolean ignore = (modelSetFileName.equals(JC.ZAP_TITLE) || modelSetFileName 384 .equals("")); 385 if (ignore) { 386 menuSetLabel(menu, ""); 387 menuEnable(menu, false); 388 } else { 389 menuSetLabel(menu, GT.o(GT.$(text), modelSetFileName)); 390 menuEnable(menu, true); 391 } 392 } 393 getMenuText(String key)394 private String getMenuText(String key) { 395 String str = menuText.getProperty(key); 396 return (str == null ? key : str); 397 } 398 updateSelectMenu()399 protected void updateSelectMenu() { 400 SC menu = htMenus.get("selectMenuText"); 401 if (menu == null) 402 return; 403 menuEnable(menu, ac != 0); 404 menuSetLabel(menu, gti("selectMenuText", vwr.slm.getSelectionCount())); 405 } 406 updateElementsComputedMenu(BS elementsPresentBitSet)407 protected void updateElementsComputedMenu(BS elementsPresentBitSet) { 408 SC menu = htMenus.get("elementsComputedMenu"); 409 if (menu == null) 410 return; 411 menuRemoveAll(menu, 0); 412 menuEnable(menu, false); 413 if (elementsPresentBitSet == null) 414 return; 415 for (int i = elementsPresentBitSet.nextSetBit(0); i >= 0; i = elementsPresentBitSet 416 .nextSetBit(i + 1)) { 417 String elementName = Elements.elementNameFromNumber(i); 418 String elementSymbol = Elements.elementSymbolFromNumber(i); 419 String entryName = elementSymbol + " - " + elementName; 420 menuCreateItem(menu, entryName, "SELECT " + elementName, null); 421 } 422 for (int i = Elements.firstIsotope; i < Elements.altElementMax; ++i) { 423 int n = Elements.elementNumberMax + i; 424 if (elementsPresentBitSet.get(n)) { 425 n = Elements.altElementNumberFromIndex(i); 426 String elementName = Elements.elementNameFromNumber(n); 427 String elementSymbol = Elements.elementSymbolFromNumber(n); 428 String entryName = elementSymbol + " - " + elementName; 429 menuCreateItem(menu, entryName, "SELECT " + elementName, null); 430 } 431 } 432 menuEnable(menu, true); 433 } 434 updateSpectraMenu()435 protected void updateSpectraMenu() { 436 SC menu = htMenus.get("spectraMenu"); 437 if (menu == null) 438 return; 439 SC menuh = htMenus.get("hnmrMenu"); 440 if (menuh != null) 441 menuRemoveAll(menuh, 0); 442 SC menuc = htMenus.get("cnmrMenu"); 443 if (menuc != null) 444 menuRemoveAll(menuc, 0); 445 menuRemoveAll(menu, 0); 446 // yes binary | not logical || here -- need to try to set both 447 boolean isOK = setSpectraMenu(menuh, hnmrPeaks) 448 | setSpectraMenu(menuc, cnmrPeaks); 449 if (isOK) { 450 if (menuh != null) 451 menuAddSubMenu(menu, menuh); 452 if (menuc != null) 453 menuAddSubMenu(menu, menuc); 454 } 455 menuEnable(menu, isOK); 456 } 457 setSpectraMenu(SC menu, Lst<String> peaks)458 private boolean setSpectraMenu(SC menu, Lst<String> peaks) { 459 int n = (peaks == null ? 0 : peaks.size()); 460 if (n == 0) 461 return false; 462 if (menu == null) 463 return false; 464 menuEnable(menu, false); 465 for (int i = 0; i < n; i++) { 466 String peak = peaks.get(i); 467 String title = PT.getQuotedAttribute(peak, "title"); 468 String atoms = PT.getQuotedAttribute(peak, "atoms"); 469 if (atoms != null) 470 menuCreateItem(menu, title, 471 "select visible & (@" + PT.rep(atoms, ",", " or @") + ")", "Focus" 472 + i); 473 } 474 menuEnable(menu, true); 475 return true; 476 } 477 updateHeteroComputedMenu(Map<String, String> htHetero)478 protected void updateHeteroComputedMenu(Map<String, String> htHetero) { 479 SC menu = htMenus.get("PDBheteroComputedMenu"); 480 if (menu == null) 481 return; 482 menuRemoveAll(menu, 0); 483 menuEnable(menu, false); 484 if (htHetero == null) 485 return; 486 int n = 0; 487 for (Map.Entry<String, String> hetero : htHetero.entrySet()) { 488 String heteroCode = hetero.getKey(); 489 String heteroName = hetero.getValue(); 490 if (heteroName.length() > 20) 491 heteroName = heteroName.substring(0, 20) + "..."; 492 String entryName = heteroCode + " - " + heteroName; 493 menuCreateItem(menu, entryName, "SELECT [" + heteroCode + "]", null); 494 n++; 495 } 496 menuEnable(menu, (n > 0)); 497 } 498 499 @SuppressWarnings("unchecked") updateSurfMoComputedMenu(Map<String, Object> moData)500 protected void updateSurfMoComputedMenu(Map<String, Object> moData) { 501 SC menu = htMenus.get("surfMoComputedMenuText"); 502 if (menu == null) 503 return; 504 menuRemoveAll(menu, 0); 505 Lst<Map<String, Object>> mos = (moData == null ? null 506 : (Lst<Map<String, Object>>) (moData.get("mos"))); 507 int nOrb = (mos == null ? 0 : mos.size()); 508 String text = getMenuText("surfMoComputedMenuText"); 509 if (nOrb == 0) { 510 menuSetLabel(menu, GT.o(GT.$(text), "")); 511 menuEnable(menu, false); 512 return; 513 } 514 menuSetLabel(menu, GT.i(GT.$(text), nOrb)); 515 menuEnable(menu, true); 516 SC subMenu = menu; 517 int nmod = (nOrb % itemMax); 518 if (nmod == 0) 519 nmod = itemMax; 520 int pt = (nOrb > itemMax ? 0 : Integer.MIN_VALUE); 521 for (int i = nOrb; --i >= 0;) { 522 if (pt >= 0 && (pt++ % nmod) == 0) { 523 if (pt == nmod + 1) 524 nmod = itemMax; 525 String id = "mo" + pt + "Menu"; 526 subMenu = menuNewSubMenu(Math.max(i + 2 - nmod, 1) + "..." + (i + 1), 527 menuGetId(menu) + "." + id); 528 menuAddSubMenu(menu, subMenu); 529 htMenus.put(id, subMenu); 530 pt = 1; 531 } 532 Map<String, Object> mo = mos.get(i); 533 String entryName = "#" 534 + (i + 1) 535 + " " 536 + (mo.containsKey("type") ? mo.get("type") + " " : "") 537 + (mo.containsKey("symmetry") ? mo.get("symmetry") + " " 538 : "") 539 + (mo.containsKey("occupancy") ? "(" + mo.get("occupancy") + ") " : "") 540 541 + (mo.containsKey("energy") ? mo.get("energy") : ""); 542 String script = "mo " + (i + 1); 543 menuCreateItem(subMenu, entryName, script, null); 544 } 545 } 546 updateFileTypeDependentMenus()547 protected void updateFileTypeDependentMenus() { 548 for (int i = NotPDB.size(); --i >= 0;) 549 menuEnable(NotPDB.get(i), !isPDB); 550 for (int i = PDBOnly.size(); --i >= 0;) 551 menuEnable(PDBOnly.get(i), isPDB); 552 for (int i = UnitcellOnly.size(); --i >= 0;) 553 menuEnable(UnitcellOnly.get(i), isUnitCell); 554 for (int i = FileUnitOnly.size(); --i >= 0;) 555 menuEnable(FileUnitOnly.get(i), isUnitCell || fileHasUnitCell); 556 for (int i = FileMolOnly.size(); --i >= 0;) 557 menuEnable(FileMolOnly.get(i), isUnitCell || fileHasUnitCell); 558 for (int i = SingleModelOnly.size(); --i >= 0;) 559 menuEnable(SingleModelOnly.get(i), isLastFrame); 560 for (int i = FramesOnly.size(); --i >= 0;) 561 menuEnable(FramesOnly.get(i), isMultiFrame); 562 for (int i = VibrationOnly.size(); --i >= 0;) 563 menuEnable(VibrationOnly.get(i), isVibration); 564 for (int i = SymmetryOnly.size(); --i >= 0;) 565 menuEnable(SymmetryOnly.get(i), hasSymmetry && isUnitCell); 566 for (int i = ChargesOnly.size(); --i >= 0;) 567 menuEnable(ChargesOnly.get(i), haveCharges); 568 for (int i = TemperatureOnly.size(); --i >= 0;) 569 menuEnable(TemperatureOnly.get(i), haveBFactors); 570 updateSignedAppletItems(); 571 } 572 updateSceneComputedMenu()573 protected void updateSceneComputedMenu() { 574 SC menu = htMenus.get("sceneComputedMenu"); 575 if (menu == null) 576 return; 577 menuRemoveAll(menu, 0); 578 menuEnable(menu, false); 579 String[] scenes = (String[]) vwr.ms.getInfoM("scenes"); 580 if (scenes == null) 581 return; 582 for (int i = 0; i < scenes.length; i++) 583 menuCreateItem(menu, scenes[i], "restore scene " + PT.esc(scenes[i]) 584 + " 1.0", null); 585 menuEnable(menu, true); 586 } 587 updatePDBResidueComputedMenus()588 protected void updatePDBResidueComputedMenus() { 589 boolean haveMenu = false; 590 SC menu3 = htMenus.get("PDBaaResiduesComputedMenu"); 591 if (menu3 != null) { 592 menuRemoveAll(menu3, 0); 593 menuEnable(menu3, false); 594 haveMenu = true; 595 } 596 SC menu1 = htMenus.get("PDBnucleicResiduesComputedMenu"); 597 if (menu1 != null) { 598 menuRemoveAll(menu1, 0); 599 menuEnable(menu1, false); 600 haveMenu = true; 601 } 602 603 SC menu2 = htMenus.get("PDBcarboResiduesComputedMenu"); 604 if (menu2 != null) { 605 menuRemoveAll(menu2, 0); 606 menuEnable(menu2, false); 607 haveMenu = true; 608 } 609 if (modelSetInfo == null || !haveMenu) 610 return; 611 int n = (modelIndex < 0 ? 0 : modelIndex + 1); 612 String[] lists = ((String[]) modelSetInfo.get("group3Lists")); 613 group3List = (lists == null ? null : lists[n]); 614 group3Counts = (lists == null ? null 615 : ((int[][]) modelSetInfo.get("group3Counts"))[n]); 616 617 if (group3List == null) 618 return; 619 //next is correct as "<=" because it includes "UNK" 620 int nItems = 0; 621 String groupList = Group.standardGroupList; 622 if (menu3 != null) { 623 for (int i = 1; i < JC.GROUPID_AMINO_MAX; ++i) 624 nItems += updateGroup3List(menu3, 625 groupList.substring(i * 6 - 4, i * 6 - 1).trim()); 626 nItems += augmentGroup3List(menu3, "p>", true); 627 menuEnable(menu3, (nItems > 0)); 628 menuEnable(htMenus.get("PDBproteinMenu"), (nItems > 0)); 629 } 630 if (menu1 != null) { 631 nItems = augmentGroup3List(menu1, "n>", false); 632 menuEnable(menu1, nItems > 0); 633 menuEnable(htMenus.get("PDBnucleicMenu"), (nItems > 0)); 634 @SuppressWarnings("unchecked") 635 Map<String, Object> dssr = (nItems > 0 && modelIndex >= 0 636 ? (Map<String, Object>) vwr.ms.getInfo(modelIndex, "dssr") 637 : null); 638 if (dssr != null) 639 setSecStrucMenu(htMenus.get("aaStructureMenu"), dssr); 640 } 641 if (menu2 != null) { 642 nItems = augmentGroup3List(menu2, "c>", false); 643 menuEnable(menu2, nItems > 0); 644 menuEnable(htMenus.get("PDBcarboMenu"), (nItems > 0)); 645 } 646 } 647 648 @SuppressWarnings("unchecked") setSecStrucMenu(SC menu, Map<String, Object> dssr)649 private boolean setSecStrucMenu(SC menu, Map<String, Object> dssr) { 650 Map<String, Object> counts = (Map<String, Object>) dssr.get("counts"); 651 if (counts == null) 652 return false; 653 String[] keys = new String[counts.size()]; 654 counts.keySet().toArray(keys); 655 Arrays.sort(keys); 656 if (keys.length == 0) 657 return false; 658 menu.removeAll(); 659 for (int i = 0; i < keys.length; i++) 660 menuCreateItem(menu, keys[i] + " (" +counts.get(keys[i]) +")", "select modelIndex=" + modelIndex + " && within('dssr', '"+keys[i]+"');", null); 661 return true; 662 } 663 updateGroup3List(SC menu, String name)664 private int updateGroup3List(SC menu, String name) { 665 int nItems = 0; 666 int n = group3Counts[group3List.indexOf(name) / 6]; 667 name = name.trim(); 668 String script = null; 669 if (n > 0) { 670 script = "SELECT " + name; 671 name += " (" + n + ")"; 672 nItems++; 673 } 674 SC item = menuCreateItem(menu, name, script, menuGetId(menu) + "." + name); 675 if (n == 0) 676 menuEnable(item, false); 677 return nItems; 678 } 679 augmentGroup3List(SC menu, String type, boolean addSeparator)680 private int augmentGroup3List(SC menu, String type, boolean addSeparator) { 681 int pt = JC.GROUPID_AMINO_MAX * 6 - 6; 682 // ...... p>AFN]o>ODH]n>+T ] 683 int nItems = 0; 684 while (true) { 685 pt = group3List.indexOf(type, pt); 686 if (pt < 0) 687 break; 688 if (nItems++ == 0 && addSeparator) 689 menuAddSeparator(menu); 690 int n = group3Counts[pt / 6]; 691 String heteroCode = group3List.substring(pt + 2, pt + 5); 692 String name = heteroCode + " (" + n + ")"; 693 menuCreateItem(menu, name, "SELECT [" + heteroCode + "]", menuGetId(menu) 694 + "." + name); 695 pt++; 696 } 697 return nItems; 698 } 699 updateSYMMETRYComputedMenus()700 protected void updateSYMMETRYComputedMenus() { 701 updateSYMMETRYSelectComputedMenu(); 702 updateSYMMETRYShowComputedMenu(); 703 } 704 705 @SuppressWarnings("unchecked") updateSYMMETRYShowComputedMenu()706 protected void updateSYMMETRYShowComputedMenu() { 707 SC menu = htMenus.get("SYMMETRYShowComputedMenu"); 708 if (menu == null) 709 return; 710 menuRemoveAll(menu, 0); 711 menuEnable(menu, false); 712 if (!hasSymmetry || modelIndex < 0) 713 return; 714 Map<String, Object> info = (Map<String, Object>) vwr.getProperty( 715 "DATA_API", "spaceGroupInfo", null); 716 if (info == null) 717 return; 718 Object[][] infolist = (Object[][]) info.get("operations"); 719 if (infolist == null) 720 return; 721 String name = (String) info.get("spaceGroupName"); 722 menuSetLabel(menu, name == null ? GT.$("Space Group") : name); 723 SC subMenu = menu; 724 int pt = (infolist.length > itemMax ? 0 : Integer.MIN_VALUE); 725 for (int i = 0; i < infolist.length; i++) { 726 if (pt >= 0 && (pt++ % itemMax) == 0) { 727 String id = "drawsymop" + pt + "Menu"; 728 subMenu = menuNewSubMenu( 729 (i + 1) + "..." + Math.min(i + itemMax, infolist.length), 730 menuGetId(menu) + "." + id); 731 menuAddSubMenu(menu, subMenu); 732 htMenus.put(id, subMenu); 733 pt = 1; 734 } 735 if (i == 0) 736 menuEnable( 737 menuCreateItem(subMenu, GT.$("none"), "draw sym_* delete", null), 738 true); 739 String sym = (String) infolist[i][1]; // XYZoriginal 740 if (sym.indexOf("x1") < 0) 741 sym = (String) infolist[i][0]; // normalized XYZ 742 String entryName = (i + 1) + " " + infolist[i][2] + " (" + sym + ")"; 743 menuEnable( 744 menuCreateItem(subMenu, entryName, "draw SYMOP " + (i + 1), null), 745 true); 746 } 747 menuEnable(menu, true); 748 } 749 updateSYMMETRYSelectComputedMenu()750 protected void updateSYMMETRYSelectComputedMenu() { 751 SC menu = htMenus.get("SYMMETRYSelectComputedMenu"); 752 if (menu == null) 753 return; 754 menuRemoveAll(menu, 0); 755 menuEnable(menu, false); 756 if (!hasSymmetry || modelIndex < 0) 757 return; 758 String[] list = (String[]) modelInfo.get("symmetryOperations"); 759 if (list == null) 760 return; 761 int[] cellRange = (int[]) modelInfo.get("unitCellRange"); 762 boolean haveUnitCellRange = (cellRange != null); 763 SC subMenu = menu; 764 int nmod = itemMax; 765 int pt = (list.length > itemMax ? 0 : Integer.MIN_VALUE); 766 for (int i = 0; i < list.length; i++) { 767 if (pt >= 0 && (pt++ % nmod) == 0) { 768 String id = "symop" + pt + "Menu"; 769 subMenu = menuNewSubMenu( 770 (i + 1) + "..." + Math.min(i + itemMax, list.length), 771 menuGetId(menu) + "." + id); 772 menuAddSubMenu(menu, subMenu); 773 htMenus.put(id, subMenu); 774 pt = 1; 775 } 776 String entryName = "symop=" + (i + 1) + " # " + list[i]; 777 menuEnable( 778 menuCreateItem(subMenu, entryName, "SELECT symop=" + (i + 1), null), 779 haveUnitCellRange); 780 } 781 menuEnable(menu, true); 782 } 783 updateFRAMESbyModelComputedMenu()784 protected void updateFRAMESbyModelComputedMenu() { 785 //allowing this in case we move it later 786 SC menu = htMenus.get("FRAMESbyModelComputedMenu"); 787 if (menu == null) 788 return; 789 menuEnable(menu, (modelCount > 0)); 790 menuSetLabel(menu, (modelIndex < 0 ? gti("allModelsText", modelCount) 791 : gto("modelMenuText", (modelIndex + 1) + "/" + modelCount))); 792 menuRemoveAll(menu, 0); 793 if (modelCount < 1) 794 return; 795 if (modelCount > 1) 796 menuCreateCheckboxItem(menu, GT.$("All"), "frame 0 ##", null, 797 (modelIndex < 0), false); 798 799 SC subMenu = menu; 800 int pt = (modelCount > itemMax ? 0 : Integer.MIN_VALUE); 801 for (int i = 0; i < modelCount; i++) { 802 if (pt >= 0 && (pt++ % itemMax) == 0) { 803 String id = "model" + pt + "Menu"; 804 subMenu = menuNewSubMenu( 805 (i + 1) + "..." + Math.min(i + itemMax, modelCount), 806 menuGetId(menu) + "." + id); 807 menuAddSubMenu(menu, subMenu); 808 htMenus.put(id, subMenu); 809 pt = 1; 810 } 811 String script = "" + vwr.getModelNumberDotted(i); 812 String entryName = vwr.getModelName(i); 813 String spectrumTypes = (String) vwr.ms.getInfo(i, 814 "spectrumTypes"); 815 if (spectrumTypes != null && entryName.startsWith(spectrumTypes)) 816 spectrumTypes = null; 817 if (!entryName.equals(script)) { 818 int ipt = entryName.indexOf(";PATH"); 819 if (ipt >= 0) 820 entryName = entryName.substring(0, ipt); 821 if (entryName.indexOf("Model[") == 0 822 && (ipt = entryName.indexOf("]:")) >= 0) 823 entryName = entryName.substring(ipt + 2); 824 entryName = script + ": " + entryName; 825 } 826 if (entryName.length() > 60) 827 entryName = entryName.substring(0, 55) + "..."; 828 if (spectrumTypes != null) 829 entryName += " (" + spectrumTypes + ")"; 830 menuCreateCheckboxItem(subMenu, entryName, "model " + script + " ##", 831 null, (modelIndex == i), false); 832 } 833 } 834 updateConfigurationComputedMenu()835 protected void updateConfigurationComputedMenu() { 836 SC menu = htMenus.get("configurationComputedMenu"); 837 if (menu == null) 838 return; 839 menuEnable(menu, isMultiConfiguration); 840 if (!isMultiConfiguration) 841 return; 842 int nAltLocs = altlocs.length(); 843 menuSetLabel(menu, gti("configurationMenuText", nAltLocs)); 844 menuRemoveAll(menu, 0); 845 String script = "hide none ##CONFIG"; 846 menuCreateCheckboxItem(menu, GT.$("All"), script, null, 847 (updateMode == UPDATE_CONFIG && configurationSelected.equals(script)), 848 false); 849 for (int i = 0; i < nAltLocs; i++) { 850 script = "configuration " + (i + 1) 851 + "; hide thisModel and not selected ##CONFIG"; 852 String entryName = "" + (i + 1) + " -- \"" + altlocs.charAt(i) + "\""; 853 menuCreateCheckboxItem( 854 menu, 855 entryName, 856 script, 857 null, 858 (updateMode == UPDATE_CONFIG && configurationSelected.equals(script)), 859 false); 860 } 861 } 862 863 private final String[] noZapped = { "surfaceMenu", "measureMenu", 864 "pickingMenu", "computationMenu", 865 "SIGNEDJAVAcaptureMenuSPECIAL" }; 866 867 @SuppressWarnings("unchecked") updateModelSetComputedMenu()868 protected void updateModelSetComputedMenu() { 869 SC menu = htMenus.get("modelSetMenu"); 870 if (menu == null) 871 return; 872 menuRemoveAll(menu, 0); 873 menuSetLabel(menu, nullModelSetName); 874 menuEnable(menu, false); 875 for (int i = noZapped.length; --i >= 0;) 876 menuEnable(htMenus.get(noZapped[i]), !isZapped); 877 if (modelSetName == null || isZapped) 878 return; 879 if (isMultiFrame) { 880 modelSetName = gti("modelSetCollectionText", modelCount); 881 if (modelSetName.length() > titleWidthMax) 882 modelSetName = modelSetName.substring(0, titleWidthMax) + "..."; 883 } else if (vwr.getBooleanProperty("hideNameInPopup")) { 884 modelSetName = getMenuText("hiddenModelSetText"); 885 } else if (modelSetName.length() > titleWidthMax) { 886 modelSetName = modelSetName.substring(0, titleWidthMax) + "..."; 887 } 888 menuSetLabel(menu, modelSetName); 889 menuEnable(menu, true); 890 891 // 100 here is totally arbitrary. You can do a minimization on any number of atoms 892 menuEnable(htMenus.get("computationMenu"), ac <= 100); 893 addMenuItem(menu, gti("atomsText", ac)); 894 addMenuItem(menu, gti("bondsText", vwr.ms.getBondCountInModel(modelIndex))); 895 if (isPDB) { 896 menuAddSeparator(menu); 897 addMenuItem(menu, 898 gti("groupsText", vwr.ms.getGroupCountInModel(modelIndex))); 899 addMenuItem(menu, 900 gti("chainsText", vwr.ms.getChainCountInModelWater(modelIndex, false))); 901 addMenuItem(menu, 902 gti("polymersText", vwr.ms.getBioPolymerCountInModel(modelIndex))); 903 SC submenu = htMenus.get("BiomoleculesMenu"); 904 if (submenu == null) { 905 submenu = menuNewSubMenu(GT.$(getMenuText("biomoleculesMenuText")), 906 menuGetId(menu) + ".biomolecules"); 907 menuAddSubMenu(menu, submenu); 908 } 909 menuRemoveAll(submenu, 0); 910 menuEnable(submenu, false); 911 Lst<Map<String, Object>> biomolecules; 912 if (modelIndex >= 0 913 && (biomolecules = (Lst<Map<String, Object>>) vwr 914 .ms.getInfo(modelIndex, "biomolecules")) != null) { 915 menuEnable(submenu, true); 916 int nBiomolecules = biomolecules.size(); 917 for (int i = 0; i < nBiomolecules; i++) { 918 String script = (isMultiFrame ? "" 919 : "save orientation;load \"\" FILTER \"biomolecule " + (i + 1) 920 + "\";restore orientation;"); 921 int nAtoms = ((Integer) biomolecules.get(i).get("atomCount")) 922 .intValue(); 923 String entryName = gto(isMultiFrame ? "biomoleculeText" 924 : "loadBiomoleculeText", new Object[] { Integer.valueOf(i + 1), 925 Integer.valueOf(nAtoms) }); 926 menuCreateItem(submenu, entryName, script, null); 927 } 928 } 929 } 930 if (isApplet && !vwr.getBooleanProperty("hideNameInPopup")) { 931 menuAddSeparator(menu); 932 menuCreateItem(menu, gto("viewMenuText", modelSetFileName), "show url", 933 null); 934 } 935 } 936 gti(String s, int n)937 private String gti(String s, int n) { 938 return GT.i(GT.$(getMenuText(s)), n); 939 } 940 gto(String s, Object o)941 private String gto(String s, Object o) { 942 return GT.o(GT.$(getMenuText(s)), o); 943 } 944 updateAboutSubmenu()945 protected void updateAboutSubmenu() { 946 if (isApplet) 947 setText("APPLETid", vwr.appletName); 948 949 /** 950 * @j2sNative 951 * 952 */ 953 { 954 Runtime runtime = Runtime.getRuntime(); 955 int n = runtime.availableProcessors(); 956 if (n > 0) 957 setText("JAVAprocessors", GT.i(GT.$("{0} processors"), n)); 958 setText("JAVAmemTotal", 959 GT.i(GT.$("{0} MB total"), convertToMegabytes(runtime.totalMemory()))); 960 // memFree.setText(GT.i(GT.$("{0} MB free"), convertToMegabytes(runtime.freeMemory()))); 961 setText("JAVAmemMax", 962 GT.i(GT.$("{0} MB maximum"), convertToMegabytes(runtime.maxMemory()))); 963 } 964 965 } 966 updateLanguageSubmenu()967 protected void updateLanguageSubmenu() { 968 SC menu = htMenus.get("languageComputedMenu"); 969 if (menu == null) 970 return; 971 menuRemoveAll(menu, 0); 972 String language = GT.getLanguage(); 973 String id = menuGetId(menu); 974 Language[] languages = GT.getLanguageList(null); 975 for (int i = 0, p = 0; i < languages.length; i++) { 976 if (language.equals(languages[i].code)) 977 languages[i].display = true; 978 if (languages[i].display) { 979 String code = languages[i].code; 980 String name = languages[i].language; 981 String nativeName = languages[i].nativeLanguage; 982 String menuLabel = code + " - " + GT.$(name); 983 if ((nativeName != null) && (!nativeName.equals(GT.$(name)))) { 984 menuLabel += " - " + nativeName; 985 } 986 if (p++ > 0 && (p % 4 == 1)) 987 menuAddSeparator(menu); 988 menuCreateCheckboxItem(menu, menuLabel, "language = \"" + code 989 + "\" ##" + name, id + "." + code, language.equals(code), false); 990 } 991 } 992 } 993 updateSpecialMenuItem(SC m)994 protected void updateSpecialMenuItem(SC m) { 995 m.setText(getSpecialLabel(m.getName(), m.getText())); 996 } 997 998 /** 999 * menus or menu items with SPECIAL in their name are sent here for on-the-fly 1000 * labeling 1001 * 1002 * @param name 1003 * @param text 1004 * @return revised text 1005 */ getSpecialLabel(String name, String text)1006 protected String getSpecialLabel(String name, String text) { 1007 int pt = text.indexOf(" ("); 1008 if (pt < 0) 1009 pt = text.length(); 1010 String info = null; 1011 if (name.indexOf("captureLooping") >= 0) 1012 info = (vwr.am.animationReplayMode == T.once ? "ONCE" : "LOOP"); 1013 else if (name.indexOf("captureFps") >= 0) 1014 info = "" + vwr.getInt(T.animationfps); 1015 else if (name.indexOf("captureMenu") >= 0) 1016 info = (vwr.captureParams == null ? GT.$("not capturing") : vwr.fm 1017 .getFilePath((String) vwr.captureParams.get("captureFileName"), 1018 false, true) 1019 + " " + vwr.captureParams.get("captureCount")); 1020 return (info == null ? text : text.substring(0, pt) + " (" + info + ")"); 1021 } 1022 1023 } 1024