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