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