001/***************************************************************************** 002 * Copyright by The HDF Group. * 003 * Copyright by the Board of Trustees of the University of Illinois. * 004 * All rights reserved. * 005 * * 006 * This file is part of the HDF Java Products distribution. * 007 * The full copyright notice, including terms governing use, modification, * 008 * and redistribution, is contained in the files COPYING and Copyright.html. * 009 * COPYING can be found at the root of the source code distribution tree. * 010 * Or, see https://support.hdfgroup.org/products/licenses.html * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.view.dialog; 016 017import java.io.InputStream; 018import java.math.BigInteger; 019import java.net.URL; 020import java.net.URLClassLoader; 021import java.util.Iterator; 022import java.util.List; 023import java.util.Scanner; 024import java.util.StringTokenizer; 025 026import org.eclipse.swt.SWT; 027import org.eclipse.swt.browser.Browser; 028import org.eclipse.swt.events.DisposeEvent; 029import org.eclipse.swt.events.DisposeListener; 030import org.eclipse.swt.events.SelectionAdapter; 031import org.eclipse.swt.events.SelectionEvent; 032import org.eclipse.swt.graphics.Point; 033import org.eclipse.swt.graphics.Rectangle; 034import org.eclipse.swt.layout.GridData; 035import org.eclipse.swt.layout.GridLayout; 036import org.eclipse.swt.widgets.Button; 037import org.eclipse.swt.widgets.Combo; 038import org.eclipse.swt.widgets.Composite; 039import org.eclipse.swt.widgets.Dialog; 040import org.eclipse.swt.widgets.Display; 041import org.eclipse.swt.widgets.Label; 042import org.eclipse.swt.widgets.Shell; 043import org.eclipse.swt.widgets.Text; 044 045import hdf.object.Attribute; 046import hdf.object.Datatype; 047import hdf.object.FileFormat; 048import hdf.object.Group; 049import hdf.object.HObject; 050import hdf.object.MetaDataContainer; 051 052import hdf.view.Tools; 053import hdf.view.ViewProperties; 054 055/** 056 * NewStringAttributeDialog displays components for adding a new attribute. 057 * 058 * @author Jordan T. Henderson 059 * @version 2.4 1/7/2016 060 */ 061public class NewStringAttributeDialog extends NewDataObjectDialog { 062 063 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NewStringAttributeDialog.class); 064 065 /** the default length of a string attribute */ 066 public static final int DEFAULT_STRING_ATTRIBUTE_LENGTH = 256; 067 068 /** TextField for entering the name of the dataset */ 069 private Text nameField; 070 071 /** TextField for entering the attribute value. */ 072 private Text valueField; 073 074 /** The Choice of the object list */ 075 private Combo objChoice; 076 077 private Button h4GrAttrRadioButton; 078 079 private Label arrayLengthLabel; 080 081 /** If the attribute should be attached to a hdf4 object */ 082 protected boolean isH4; 083 /** If the attribute should be attached to a netcdf object */ 084 protected boolean isN3; 085 086 /** 087 * Constructs a NewStringAttributeDialog with specified object (dataset, group, or 088 * image) for the new attribute to be attached to. 089 * 090 * @param parent 091 * the parent shell of the dialog 092 * @param pObject 093 * the parent object which the new attribute is attached to. 094 * @param objs 095 * the list of all objects. 096 */ 097 public NewStringAttributeDialog(Shell parent, HObject pObject, List<HObject> objs) { 098 super(parent, pObject, objs); 099 isH4 = pObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4)); 100 isN3 = pObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_NC3)); 101 } 102 103 /** 104 * Open the NewStringAttributeDialog for adding a new attribute. 105 */ 106 public void open() { 107 Shell parent = getParent(); 108 shell = new Shell(parent, SWT.SHELL_TRIM | SWT.APPLICATION_MODAL); 109 shell.setFont(curFont); 110 shell.setText("New Attribute..."); 111 shell.setImage(ViewProperties.getHdfIcon()); 112 shell.setLayout(new GridLayout(1, true)); 113 114 115 // Create content region 116 Composite content = new Composite(shell, SWT.NONE); 117 content.setLayout(new GridLayout(2, false)); 118 content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 119 120 Label label = new Label(content, SWT.LEFT); 121 label.setFont(curFont); 122 label.setText("Name: "); 123 124 nameField = new Text(content, SWT.SINGLE | SWT.BORDER); 125 nameField.setFont(curFont); 126 nameField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 127 128 label = new Label(content, SWT.LEFT); 129 label.setFont(curFont); 130 label.setText("Type: "); 131 132 Composite optionsComposite = new Composite(content, SWT.NONE); 133 optionsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 134 optionsComposite.setLayout(new GridLayout( 135 (!isH5 && (parentObj instanceof Group) && ((Group) parentObj).isRoot()) ? 5 : 3, 136 false) 137 ); 138 139 // Dummy label 140 label = new Label(optionsComposite, SWT.LEFT); 141 label.setFont(curFont); 142 label.setText(""); 143 144 if (!isH5 && (parentObj instanceof Group) && ((Group) parentObj).isRoot()) { 145 label = new Label(optionsComposite, SWT.LEFT); 146 label.setFont(curFont); 147 label.setText(""); 148 149 label = new Label(optionsComposite, SWT.LEFT); 150 label.setFont(curFont); 151 label.setText(""); 152 } 153 154 createDatatypeWidget(); 155 156 if (!isH5 && (parentObj instanceof Group) && ((Group) parentObj).isRoot()) { 157 Button h4SdAttrRadioButton = new Button(optionsComposite, SWT.RADIO); 158 h4SdAttrRadioButton.setFont(curFont); 159 h4SdAttrRadioButton.setText("SD"); 160 h4SdAttrRadioButton.setSelection(true); 161 162 h4GrAttrRadioButton = new Button(optionsComposite, SWT.RADIO); 163 h4GrAttrRadioButton.setFont(curFont); 164 h4GrAttrRadioButton.setText("GR"); 165 } 166 167 arrayLengthLabel = new Label(content, SWT.LEFT); 168 arrayLengthLabel.setFont(curFont); 169 arrayLengthLabel.setText("Array Size: "); 170 171 lengthField = new Text(content, SWT.SINGLE | SWT.BORDER); 172 lengthField.setFont(curFont); 173 lengthField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 174 lengthField.setTextLimit(30); 175 lengthField.setText("1"); 176 177 label = new Label(content, SWT.LEFT); 178 label.setFont(curFont); 179 label.setText("Value: "); 180 181 valueField = new Text(content, SWT.SINGLE | SWT.BORDER); 182 valueField.setFont(curFont); 183 valueField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 184 valueField.setText("0"); 185 186 label = new Label(content, SWT.LEFT); 187 label.setFont(curFont); 188 label.setText("Object List: "); 189 190 objChoice = new Combo(content, SWT.DROP_DOWN | SWT.READ_ONLY); 191 objChoice.setFont(curFont); 192 objChoice.setEnabled(true); 193 objChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 194 objChoice.addSelectionListener(new SelectionAdapter() { 195 @Override 196 public void widgetSelected(SelectionEvent e) { 197 String objName = objChoice.getItem(objChoice.getSelectionIndex()); 198 199 long[] ref = null; 200 try { 201 HObject obj = fileFormat.get(objName); 202 ref = obj.getOID(); 203 } 204 catch (Exception ex) { 205 log.debug("object id:", ex); 206 } 207 208 if (ref != null) { 209 if (valueField.getText().length() > 1) { 210 valueField.setText(valueField.getText() + "," + ref); 211 StringTokenizer st = new StringTokenizer(valueField.getText(), ","); 212 lengthField.setText(String.valueOf(st.countTokens())); 213 } 214 else { 215 valueField.setText(String.valueOf(ref)); 216 lengthField.setText("1"); 217 } 218 } 219 } 220 }); 221 222 Iterator<?> it = objList.iterator(); 223 HObject hobj; 224 while (it.hasNext()) { 225 hobj = (HObject) it.next(); 226 227 if (hobj instanceof Group) { 228 if (((Group) hobj).isRoot()) continue; 229 } 230 231 objChoice.add(hobj.getFullName()); 232 } 233 234 // Add label to take up extra space when resizing dialog 235 label = new Label(content, SWT.LEFT); 236 label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); 237 238 // Create Ok/Cancel/Help button region 239 Composite buttonComposite = new Composite(shell, SWT.NONE); 240 buttonComposite.setLayout(new GridLayout(3, false)); 241 buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 242 243 Button okButton = new Button(buttonComposite, SWT.PUSH); 244 okButton.setFont(curFont); 245 okButton.setText(" &OK "); 246 okButton.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); 247 okButton.addSelectionListener(new SelectionAdapter() { 248 @Override 249 public void widgetSelected(SelectionEvent e) { 250 if (createAttribute()) { 251 shell.dispose(); 252 } 253 } 254 }); 255 256 Button cancelButton = new Button(buttonComposite, SWT.PUSH); 257 cancelButton.setFont(curFont); 258 cancelButton.setText(" &Cancel "); 259 cancelButton.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, false, false)); 260 cancelButton.addSelectionListener(new SelectionAdapter() { 261 @Override 262 public void widgetSelected(SelectionEvent e) { 263 newObject = null; 264 shell.dispose(); 265 } 266 }); 267 268 Button helpButton = new Button(buttonComposite, SWT.PUSH); 269 helpButton.setFont(curFont); 270 helpButton.setText(" &Help "); 271 helpButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false)); 272 helpButton.addSelectionListener(new SelectionAdapter() { 273 @Override 274 public void widgetSelected(SelectionEvent e) { 275 new HelpDialog(shell).open(); 276 } 277 }); 278 279 shell.pack(); 280 281 shell.addDisposeListener(new DisposeListener() { 282 @Override 283 public void widgetDisposed(DisposeEvent e) { 284 if (curFont != null) curFont.dispose(); 285 } 286 }); 287 288 shell.setMinimumSize(shell.computeSize(SWT.DEFAULT, SWT.DEFAULT)); 289 290 Rectangle parentBounds = parent.getBounds(); 291 Point shellSize = shell.getSize(); 292 shell.setLocation((parentBounds.x + (parentBounds.width / 2)) - (shellSize.x / 2), 293 (parentBounds.y + (parentBounds.height / 2)) - (shellSize.y / 2)); 294 295 shell.open(); 296 297 Display display = shell.getDisplay(); 298 while (!shell.isDisposed()) 299 if (!display.readAndDispatch()) 300 display.sleep(); 301 } 302 303 @SuppressWarnings("unchecked") 304 private boolean createAttribute() { 305 Object value = null; 306 String strValue = valueField.getText(); 307 308 String attrName = nameField.getText(); 309 if (attrName != null) { 310 attrName = attrName.trim(); 311 } 312 313 if ((attrName == null) || (attrName.length() < 1)) { 314 Tools.showError(shell, "Create", "No attribute name specified."); 315 return false; 316 } 317 318 String lengthStr = lengthField.getText(); 319 log.trace("Name is {} : Length={} and Value={}", attrName, lengthStr, strValue); 320 321 int arraySize = 0; 322 if ((lengthStr == null) || (lengthStr.length() <= 0)) { 323 arraySize = 1; 324 } 325 else { 326 try { 327 arraySize = Integer.parseInt(lengthStr); 328 } 329 catch (Exception e) { 330 arraySize = -1; 331 } 332 } 333 334 if (arraySize <= 0) { 335 Tools.showError(shell, "Create", "Invalid attribute length."); 336 return false; 337 } 338 339 StringTokenizer st = new StringTokenizer(strValue, ","); 340 int count = Math.min(arraySize, st.countTokens()); 341 String theToken; 342 log.trace("Count of Values is {}", count); 343 344 // set datatype class 345 Datatype datatype = super.createNewDatatype(null); 346 if (isVLen) { 347 log.trace("Attribute isVLen={} and tsize={}", isVLen, tsize); 348 String[] strArray = { strValue }; 349 value = strArray; 350 } 351 else { 352 if (tclass == Datatype.CLASS_STRING) { 353 if (!isVlenStr) { 354 if (strValue.length() > tsize) { 355 strValue = strValue.substring(0, tsize); 356 } 357 } 358 359 String[] strArray = { strValue }; 360 value = strArray; 361 362 if (isH5) { 363 arraySize = 1; // support string type 364 } 365 else { 366 arraySize = tsize; // array of characters 367 } 368 log.trace("Attribute CLASS_STRING: isVLen={} and tsize={} and arraySize={}", isVLen, tsize, arraySize); 369 } 370 else if (tclass == Datatype.CLASS_REFERENCE) { 371 arraySize = st.countTokens(); 372 long[] ref = new long[arraySize]; 373 for (int j = 0; j < arraySize; j++) { 374 theToken = st.nextToken().trim(); 375 try { 376 ref[j] = Long.parseLong(theToken); 377 } 378 catch (NumberFormatException ex) { 379 Tools.showError(shell, "Create", ex.getMessage()); 380 return false; 381 } 382 } 383 384 value = ref; 385 log.trace("Attribute CLASS_REFERENCE: tsize={} and arraySize={}", tsize, arraySize); 386 } 387 else if (tclass == Datatype.CLASS_INTEGER) { 388 if (tsign == Datatype.SIGN_NONE) { 389 if (tsize == 1) { 390 byte[] b = new byte[arraySize]; 391 short sv = 0; 392 for (int j = 0; j < count; j++) { 393 theToken = st.nextToken().trim(); 394 try { 395 sv = Short.parseShort(theToken); 396 } 397 catch (NumberFormatException ex) { 398 Tools.showError(shell, "Create", ex.getMessage()); 399 return false; 400 } 401 if (sv < 0) { 402 sv = 0; 403 } 404 else if (sv > 255) { 405 sv = 255; 406 } 407 b[j] = (byte) sv; 408 } 409 value = b; 410 } 411 else if (tsize == 2) { 412 short[] s = new short[arraySize]; 413 int iv = 0; 414 for (int j = 0; j < count; j++) { 415 theToken = st.nextToken().trim(); 416 try { 417 iv = Integer.parseInt(theToken); 418 } 419 catch (NumberFormatException ex) { 420 Tools.showError(shell, "Create", ex.getMessage()); 421 return false; 422 } 423 if (iv < 0) { 424 iv = 0; 425 } 426 else if (iv > 65535) { 427 iv = 65535; 428 } 429 s[j] = (short) iv; 430 } 431 value = s; 432 } 433 else if ((tsize == 4) || (tsize == -1)) { 434 int[] i = new int[arraySize]; 435 long lv = 0; 436 for (int j = 0; j < count; j++) { 437 theToken = st.nextToken().trim(); 438 try { 439 lv = Long.parseLong(theToken); 440 } 441 catch (NumberFormatException ex) { 442 Tools.showError(shell, "Create", ex.getMessage()); 443 return false; 444 } 445 if (lv < 0) { 446 lv = 0; 447 } 448 if (lv > 4294967295L) { 449 lv = 4294967295L; 450 } 451 i[j] = (int) lv; 452 } 453 value = i; 454 } 455 else if (tsize == 8) { 456 long[] i = new long[arraySize]; 457 BigInteger lv = BigInteger.valueOf(0); 458 for (int j = 0; j < count; j++) { 459 theToken = st.nextToken().trim(); 460 try { 461 lv = new BigInteger(theToken); 462 } 463 catch (NumberFormatException ex) { 464 Tools.showError(shell, "Create", ex.getMessage()); 465 return false; 466 } 467 i[j] = lv.longValue(); 468 } 469 value = i; 470 } 471 } 472 else { 473 if (tsize == 1) { 474 byte[] b = new byte[arraySize]; 475 for (int j = 0; j < count; j++) { 476 theToken = st.nextToken().trim(); 477 try { 478 b[j] = Byte.parseByte(theToken); 479 } 480 catch (NumberFormatException ex) { 481 Tools.showError(shell, "Create", ex.getMessage()); 482 return false; 483 } 484 } 485 value = b; 486 } 487 else if (tsize == 2) { 488 short[] s = new short[arraySize]; 489 490 for (int j = 0; j < count; j++) { 491 theToken = st.nextToken().trim(); 492 try { 493 s[j] = Short.parseShort(theToken); 494 } 495 catch (NumberFormatException ex) { 496 Tools.showError(shell, "Create", ex.getMessage()); 497 return false; 498 } 499 } 500 value = s; 501 } 502 else if ((tsize == 4) || (tsize == -1)) { 503 int[] i = new int[arraySize]; 504 505 for (int j = 0; j < count; j++) { 506 theToken = st.nextToken().trim(); 507 try { 508 i[j] = Integer.parseInt(theToken); 509 } 510 catch (NumberFormatException ex) { 511 Tools.showError(shell, "Create", ex.getMessage()); 512 return false; 513 } 514 } 515 value = i; 516 } 517 else if (tsize == 8) { 518 long[] l = new long[arraySize]; 519 for (int j = 0; j < count; j++) { 520 theToken = st.nextToken().trim(); 521 try { 522 l[j] = Long.parseLong(theToken); 523 } 524 catch (NumberFormatException ex) { 525 Tools.showError(shell, "Create", ex.getMessage()); 526 return false; 527 } 528 } 529 value = l; 530 } 531 } 532 } 533 534 if (tclass == Datatype.CLASS_FLOAT) { 535 if ((tsize == 4) || (tsize == -1)) { 536 float[] f = new float[arraySize]; 537 for (int j = 0; j < count; j++) { 538 theToken = st.nextToken().trim(); 539 try { 540 f[j] = Float.parseFloat(theToken); 541 } 542 catch (NumberFormatException ex) { 543 Tools.showError(shell, "Create", ex.getMessage()); 544 return false; 545 } 546 if (Float.isInfinite(f[j]) || Float.isNaN(f[j])) { 547 f[j] = 0; 548 } 549 } 550 value = f; 551 } 552 else if (tsize == 8) { 553 double[] d = new double[arraySize]; 554 for (int j = 0; j < count; j++) { 555 theToken = st.nextToken().trim(); 556 try { 557 d[j] = Double.parseDouble(theToken); 558 } 559 catch (NumberFormatException ex) { 560 Tools.showError(shell, "Create", ex.getMessage()); 561 return false; 562 } 563 if (Double.isInfinite(d[j]) || Double.isNaN(d[j])) { 564 d[j] = 0; 565 } 566 } 567 value = d; 568 } 569 } 570 } 571 572 long[] dims = { arraySize }; 573 Attribute attr = null; 574 try { 575 if (isH4) 576 attr = new hdf.object.h4.H4ScalarAttribute(parentObj, attrName, datatype, dims); 577 else 578 attr = new hdf.object.nc2.NC2Attribute(parentObj, attrName, datatype, dims); 579 } 580 catch (Exception ex) { 581 Tools.showError(shell, "Create", ex.getMessage()); 582 log.debug("createAttribute(): ", ex); 583 return false; 584 } 585 if (attr ==null) { 586 Tools.showError(shell, "Create", "Attribute could not be created"); 587 log.debug("createAttribute(): failed"); 588 return false; 589 } 590 attr.setAttributeData(value); 591 592 try { 593 if (!isH5 && (parentObj instanceof Group) && ((Group) parentObj).isRoot() && h4GrAttrRadioButton.getSelection()) { 594 parentObj.getFileFormat().writeAttribute(parentObj, attr, false); 595 // don't find a good way to write HDF4 global 596 // attribute. Use the isExisted to separate the 597 // global attribute is GR or SD 598 599 if (((MetaDataContainer) parentObj).getMetadata() == null) { 600 ((MetaDataContainer) parentObj).getMetadata().add(attr); 601 } 602 } 603 else { 604 log.trace("writeMetadata() via write()"); 605 attr.writeAttribute(); 606 } 607 } 608 catch (Exception ex) { 609 Tools.showError(shell, "Create", ex.getMessage()); 610 log.debug("createAttribute(): ", ex); 611 return false; 612 } 613 614 newObject = (HObject)attr; 615 616 return true; 617 } 618 619 private class HelpDialog extends Dialog { 620 private Shell helpShell; 621 622 public HelpDialog(Shell parent) { 623 super(parent, SWT.APPLICATION_MODAL); 624 } 625 626 public void open() { 627 Shell parent = getParent(); 628 helpShell = new Shell(parent, SWT.TITLE | SWT.CLOSE | 629 SWT.RESIZE | SWT.BORDER | SWT.APPLICATION_MODAL); 630 helpShell.setFont(curFont); 631 helpShell.setText("Create New Attribute"); 632 helpShell.setImage(ViewProperties.getHdfIcon()); 633 helpShell.setLayout(new GridLayout(1, true)); 634 635 // Try to create a Browser on platforms that support it 636 try { 637 Browser browser = new Browser(helpShell, SWT.NONE); 638 browser.setFont(curFont); 639 browser.setBounds(0, 0, 500, 500); 640 browser.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 641 642 if (ClassLoader.getSystemResource("hdf/view/HDFView.class").toString().startsWith("jar")) { 643 // Attempt to load HTML help file from jar 644 try (InputStream in = getClass().getClassLoader().getResourceAsStream("hdf/view/NewAttrHelp.html")) { 645 Scanner scan = new Scanner(in); 646 StringBuilder buffer = new StringBuilder(); 647 while(scan.hasNextLine()) { 648 buffer.append(scan.nextLine()); 649 } 650 651 browser.setText(buffer.toString()); 652 653 scan.close(); 654 } 655 catch (Exception e) { 656 StringBuilder buff = new StringBuilder(); 657 buff.append("<html>") 658 .append("<body>") 659 .append("ERROR: cannot load help information.") 660 .append("</body>") 661 .append("</html>"); 662 browser.setText(buff.toString(), true); 663 } 664 } 665 else { 666 try { 667 URL url = null, url2 = null, url3 = null; 668 String rootPath = ViewProperties.getViewRoot(); 669 670 try { 671 url = new URL("file://" + rootPath + "/HDFView.jar"); 672 } 673 catch (java.net.MalformedURLException mfu) { 674 log.debug("help information:", mfu); 675 } 676 677 try { 678 url2 = new URL("file://" + rootPath + "/"); 679 } 680 catch (java.net.MalformedURLException mfu) { 681 log.debug("help information:", mfu); 682 } 683 684 try { 685 url3 = new URL("file://" + rootPath + "/src/"); 686 } 687 catch (java.net.MalformedURLException mfu) { 688 log.debug("help information:", mfu); 689 } 690 691 URL uu[] = { url, url2, url3 }; 692 try (URLClassLoader cl = new URLClassLoader(uu)) { 693 URL u = cl.findResource("hdf/view/NewAttrHelp.html"); 694 695 browser.setUrl(u.toString()); 696 } 697 catch (Exception ex) { 698 log.trace("URLClassLoader failed:", ex); 699 } 700 } 701 catch (Exception e) { 702 StringBuilder buff = new StringBuilder(); 703 buff.append("<html>") 704 .append("<body>") 705 .append("ERROR: cannot load help information.") 706 .append("</body>") 707 .append("</html>"); 708 browser.setText(buff.toString(), true); 709 } 710 } 711 712 Button okButton = new Button(helpShell, SWT.PUSH); 713 okButton.setFont(curFont); 714 okButton.setText(" &OK "); 715 okButton.setLayoutData(new GridData(SWT.CENTER, SWT.FILL, true, false)); 716 okButton.addSelectionListener(new SelectionAdapter() { 717 @Override 718 public void widgetSelected(SelectionEvent e) { 719 helpShell.dispose(); 720 } 721 }); 722 723 helpShell.pack(); 724 725 helpShell.setSize(new Point(500, 500)); 726 727 Rectangle parentBounds = parent.getBounds(); 728 Point shellSize = helpShell.getSize(); 729 helpShell.setLocation((parentBounds.x + (parentBounds.width / 2)) - (shellSize.x / 2), 730 (parentBounds.y + (parentBounds.height / 2)) - (shellSize.y / 2)); 731 732 helpShell.open(); 733 734 Display display = parent.getDisplay(); 735 while(!helpShell.isDisposed()) { 736 if (!display.readAndDispatch()) 737 display.sleep(); 738 } 739 } 740 catch (Error er) { 741 // Try opening help link in external browser if platform 742 // doesn't support SWT browser 743 Tools.showError(shell, "Browser support", 744 "Platform doesn't support Browser. Opening external link in web browser..."); 745 746 //TODO: Add support for launching in external browser 747 } 748 catch (Exception ex) { 749 log.debug("Open New Attribute Help failure: ", ex); 750 } 751 } 752 } 753 754 /** @return the new attribute created. */ 755 public Attribute getAttribute() { 756 return (Attribute)newObject; 757 } 758}