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.util.Iterator; 018import java.util.List; 019import java.util.StringTokenizer; 020import java.util.Vector; 021 022import org.eclipse.swt.SWT; 023import org.eclipse.swt.custom.CCombo; 024import org.eclipse.swt.custom.TableEditor; 025import org.eclipse.swt.events.DisposeEvent; 026import org.eclipse.swt.events.DisposeListener; 027import org.eclipse.swt.events.ModifyEvent; 028import org.eclipse.swt.events.ModifyListener; 029import org.eclipse.swt.events.SelectionAdapter; 030import org.eclipse.swt.events.SelectionEvent; 031import org.eclipse.swt.events.TraverseEvent; 032import org.eclipse.swt.events.TraverseListener; 033import org.eclipse.swt.graphics.Point; 034import org.eclipse.swt.graphics.Rectangle; 035import org.eclipse.swt.layout.GridData; 036import org.eclipse.swt.layout.GridLayout; 037import org.eclipse.swt.widgets.Button; 038import org.eclipse.swt.widgets.Combo; 039import org.eclipse.swt.widgets.Composite; 040import org.eclipse.swt.widgets.Display; 041import org.eclipse.swt.widgets.Event; 042import org.eclipse.swt.widgets.Label; 043import org.eclipse.swt.widgets.Listener; 044import org.eclipse.swt.widgets.Shell; 045import org.eclipse.swt.widgets.Table; 046import org.eclipse.swt.widgets.TableColumn; 047import org.eclipse.swt.widgets.TableItem; 048import org.eclipse.swt.widgets.Text; 049 050import hdf.object.CompoundDS; 051import hdf.object.Dataset; 052import hdf.object.Datatype; 053import hdf.object.Group; 054import hdf.object.HObject; 055import hdf.view.Tools; 056import hdf.view.ViewProperties; 057 058/** 059 * NewCompoundDatasetDialog shows a message dialog requesting user input for creating 060 * a new HDF4/5 compound dataset. 061 * 062 * @author Jordan T. Henderson 063 * @version 2.4 1/7/2015 064 */ 065public class NewCompoundDatasetDialog extends NewDataObjectDialog { 066 067 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NewCompoundDatasetDialog.class); 068 069 private static final String[] DATATYPE_NAMES = { 070 "byte (8-bit)", // 0 071 "short (16-bit)", // 1 072 "int (32-bit)", // 2 073 "unsigned byte (8-bit)", // 3 074 "unsigned short (16-bit)", // 4 075 "unsigned int (32-bit)", // 5 076 "long (64-bit)", // 6 077 "float", // 7 078 "double", // 8 079 "string", // 9 080 "enum", // 10 081 "unsigned long (64-bit)" // 11 082 }; 083 084 private Combo parentChoice, nFieldBox, templateChoice; 085 086 /** A list of current groups */ 087 private Vector<Group> groupList; 088 private Vector<CompoundDS> compoundDSList; 089 090 private int numberOfMembers; 091 092 private Table table; 093 094 private TableEditor[][] editors; 095 096 private Text nameField, currentSizeField, maxSizeField, chunkSizeField; 097 098 private Combo compressionLevel, rankChoice; 099 private Button checkCompression; 100 private Button checkContiguous, checkChunked; 101 102 /** 103 * Constructs a NewDatasetDialog with specified list of possible parent 104 * groups. 105 * 106 * @param parent 107 * the parent shell of the dialog 108 * @param pGroup 109 * the parent group which the new group is added to. 110 * @param objs 111 * the list of all objects. 112 */ 113 public NewCompoundDatasetDialog(Shell parent, Group pGroup, List<?> objs) { 114 super(parent, pGroup, objs); 115 116 numberOfMembers = 2; 117 118 groupList = new Vector<>(objs.size()); 119 compoundDSList = new Vector<>(objs.size()); 120 } 121 122 public void open() { 123 Shell parent = getParent(); 124 shell = new Shell(parent, SWT.SHELL_TRIM | SWT.APPLICATION_MODAL); 125 shell.setFont(curFont); 126 shell.setText("New Compound Dataset..."); 127 shell.setImage(ViewProperties.getHdfIcon()); 128 shell.setLayout(new GridLayout(1, false)); 129 130 131 // Create Name/Parent Group/Import field region 132 Composite fieldComposite = new Composite(shell, SWT.NONE); 133 GridLayout layout = new GridLayout(2, false); 134 layout.verticalSpacing = 0; 135 fieldComposite.setLayout(layout); 136 fieldComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 137 138 Label label = new Label(fieldComposite, SWT.LEFT); 139 label.setFont(curFont); 140 label.setText("Dataset name: "); 141 142 nameField = new Text(fieldComposite, SWT.SINGLE | SWT.BORDER); 143 nameField.setFont(curFont); 144 nameField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 145 146 label = new Label(fieldComposite, SWT.LEFT); 147 label.setFont(curFont); 148 label.setText("Parent group: "); 149 150 parentChoice = new Combo(fieldComposite, SWT.DROP_DOWN | SWT.READ_ONLY); 151 parentChoice.setFont(curFont); 152 parentChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 153 parentChoice.addSelectionListener(new SelectionAdapter() { 154 @Override 155 public void widgetSelected(SelectionEvent e) { 156 parentObj = groupList.get(parentChoice.getSelectionIndex()); 157 } 158 }); 159 160 Object obj = null; 161 Iterator<?> iterator = objList.iterator(); 162 163 while (iterator.hasNext()) { 164 obj = iterator.next(); 165 if (obj instanceof Group) { 166 Group g = (Group) obj; 167 groupList.add(g); 168 if (g.isRoot()) { 169 parentChoice.add(HObject.SEPARATOR); 170 } 171 else { 172 parentChoice.add(g.getPath() + g.getName() + HObject.SEPARATOR); 173 } 174 } 175 else if (obj instanceof CompoundDS) { 176 compoundDSList.add((CompoundDS) obj); 177 } 178 } 179 180 if (((Group) parentObj).isRoot()) { 181 parentChoice.select(parentChoice.indexOf(HObject.SEPARATOR)); 182 } 183 else { 184 parentChoice.select(parentChoice.indexOf(parentObj.getPath() + parentObj.getName() + HObject.SEPARATOR)); 185 } 186 187 label = new Label(fieldComposite, SWT.LEFT); 188 label.setFont(curFont); 189 label.setText("Import template: "); 190 191 templateChoice = new Combo(fieldComposite, SWT.DROP_DOWN | SWT.READ_ONLY); 192 templateChoice.setFont(curFont); 193 templateChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 194 templateChoice.addSelectionListener(new SelectionAdapter() { 195 @Override 196 public void widgetSelected(SelectionEvent e) { 197 CompoundDS dset = null; 198 String name = templateChoice.getItem(templateChoice.getSelectionIndex()); 199 200 log.trace("templateChoice start name={}", name); 201 for (CompoundDS ds : compoundDSList) 202 if (ds.getName().equals(name)) 203 dset = ds; 204 205 if (dset == null) return; 206 207 if (!dset.isInited()) 208 dset.init(); 209 210 int rank = dset.getRank(); 211 rankChoice.select(rank - 1); 212 long[] dims = dset.getDims(); 213 final String[] mNames = dset.getMemberNames(); 214 int[] mOrders = dset.getMemberOrders(); 215 Datatype[] mTypes = dset.getMemberTypes(); 216 217 String sizeStr = String.valueOf(dims[0]); 218 for (int i = 1; i < rank; i++) { 219 sizeStr += "x" + dims[i]; 220 } 221 currentSizeField.setText(sizeStr); 222 223 try { 224 dset.getMetadata(); 225 } // get chunking and compression info 226 catch (Exception ex) { 227 log.debug("get chunking and compression info:", ex); 228 } 229 long[] chunks = dset.getChunkSize(); 230 if (chunks != null) { 231 checkChunked.setSelection(true); 232 sizeStr = String.valueOf(chunks[0]); 233 for (int i = 1; i < rank; i++) { 234 sizeStr += "x" + chunks[i]; 235 } 236 chunkSizeField.setText(sizeStr); 237 } 238 239 String compression = dset.getCompression(); 240 if (compression != null) { 241 int clevel = -1; 242 int comp_pos = Dataset.COMPRESSION_GZIP_TXT.length(); 243 int idx = compression.indexOf(Dataset.COMPRESSION_GZIP_TXT); 244 if (idx >= 0) { 245 try { 246 clevel = Integer.parseInt(compression.substring(idx + comp_pos, idx + comp_pos +1)); 247 } 248 catch (NumberFormatException ex) { 249 clevel = -1; 250 } 251 } 252 if (clevel > 0) { 253 checkCompression.setSelection(true); 254 compressionLevel.select(clevel); 255 } 256 } 257 258 nFieldBox.select(dset.getMemberCount() - 1); 259 nFieldBox.notifyListeners(SWT.Selection, new Event()); 260 for (int i = 0; i < numberOfMembers; i++) { 261 ((Text) editors[i][0].getEditor()).setText(mNames[i]); 262 263 log.trace("mNames[{}] = {}", i, mNames[i]); 264 int typeIdx = -1; 265 int tclass = mTypes[i].getDatatypeClass(); 266 long tsize = mTypes[i].getDatatypeSize(); 267 int tsigned = mTypes[i].getDatatypeSign(); 268 if (tclass == Datatype.CLASS_ARRAY) { 269 tclass = mTypes[i].getDatatypeBase().getDatatypeClass(); 270 tsize = mTypes[i].getDatatypeBase().getDatatypeSize(); 271 tsigned = mTypes[i].getDatatypeBase().getDatatypeSign(); 272 } 273 if (tclass == Datatype.CLASS_CHAR) { 274 if (tsigned == Datatype.SIGN_NONE) { 275 if (tsize == 1) { 276 typeIdx = 3; 277 } 278 } 279 else { 280 if (tsize == 1) { 281 typeIdx = 0; 282 } 283 } 284 } 285 if (tclass == Datatype.CLASS_INTEGER) { 286 if (tsigned == Datatype.SIGN_NONE) { 287 if (tsize == 1) { 288 typeIdx = 3; 289 } 290 else if (tsize == 2) { 291 typeIdx = 4; 292 } 293 else if (tsize == 4) { 294 typeIdx = 5; 295 } 296 else { 297 typeIdx = 11; 298 } 299 } 300 else { 301 if (tsize == 1) { 302 typeIdx = 0; 303 } 304 else if (tsize == 2) { 305 typeIdx = 1; 306 } 307 else if (tsize == 4) { 308 typeIdx = 2; 309 } 310 else { 311 typeIdx = 6; 312 } 313 } 314 } 315 else if (tclass == Datatype.CLASS_FLOAT) { 316 if (tsize == 4) { 317 typeIdx = 7; 318 } 319 else { 320 typeIdx = 8; 321 } 322 } 323 else if (tclass == Datatype.CLASS_STRING) { 324 typeIdx = 9; 325 } 326 else if (tclass == Datatype.CLASS_ENUM) { 327 typeIdx = 10; 328 } 329 if (typeIdx < 0) { 330 continue; 331 } 332 log.trace("typeIdx={}", typeIdx); 333 334 CCombo typeCombo = ((CCombo) editors[i][1].getEditor()); 335 typeCombo.select(typeIdx); 336 typeCombo.notifyListeners(SWT.Selection, new Event()); 337 338 //TODO: Array size is wrong for enums and for array types. Array types such as 8x8 339 // show as size 64, not 8x8 340 if (tclass == Datatype.CLASS_STRING) { 341 ((Text) editors[i][2].getEditor()).setText(String.valueOf(tsize)); 342 } 343 else if (tclass == Datatype.CLASS_ENUM) { 344 ((Text) editors[i][2].getEditor()).setText(mTypes[i].getEnumMembersAsString()); 345 table.getItem(i).setText(2, mTypes[i].getEnumMembersAsString()); 346 } 347 else { 348 ((Text) editors[i][2].getEditor()).setText(String.valueOf(mOrders[i])); 349 } 350 } // (int i=0; i<numberOfMembers; i++) 351 } 352 }); 353 354 Iterator<CompoundDS> it = compoundDSList.iterator(); 355 while(it.hasNext()) { 356 templateChoice.add(it.next().getName()); 357 } 358 359 360 // Create Dataspace region 361 org.eclipse.swt.widgets.Group dataspaceGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE); 362 dataspaceGroup.setLayout(new GridLayout(3, true)); 363 dataspaceGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 364 dataspaceGroup.setFont(curFont); 365 dataspaceGroup.setText("Dataspace"); 366 367 label = new Label(dataspaceGroup, SWT.LEFT); 368 label.setFont(curFont); 369 label.setText("No. of dimensions"); 370 371 label = new Label(dataspaceGroup, SWT.LEFT); 372 label.setFont(curFont); 373 label.setText("Current size"); 374 375 label = new Label(dataspaceGroup, SWT.LEFT); 376 label.setFont(curFont); 377 label.setText("Max size (-1 for unlimited)"); 378 379 rankChoice = new Combo(dataspaceGroup, SWT.DROP_DOWN | SWT.READ_ONLY); 380 rankChoice.setFont(curFont); 381 rankChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 382 rankChoice.addSelectionListener(new SelectionAdapter() { 383 @Override 384 public void widgetSelected(SelectionEvent e) { 385 int rank = rankChoice.getSelectionIndex() + 1; 386 String currentSizeStr = "1"; 387 String maxSizeStr = "0"; 388 389 for (int i = 1; i < rank; i++) { 390 currentSizeStr += " x 1"; 391 maxSizeStr += " x 0"; 392 } 393 394 currentSizeField.setText(currentSizeStr); 395 maxSizeField.setText(maxSizeStr); 396 397 String currentStr = currentSizeField.getText(); 398 int idx = currentStr.lastIndexOf('x'); 399 String chunkStr = "1"; 400 401 if (rank <= 1) { 402 chunkStr = currentStr; 403 } 404 else { 405 for (int i = 1; i < rank - 1; i++) { 406 chunkStr += " x 1"; 407 } 408 if (idx > 0) { 409 chunkStr += " x " + currentStr.substring(idx + 1); 410 } 411 } 412 413 chunkSizeField.setText(chunkStr); 414 } 415 }); 416 417 for (int i = 1; i < 33; i++) { 418 rankChoice.add(String.valueOf(i)); 419 } 420 421 currentSizeField = new Text(dataspaceGroup, SWT.SINGLE | SWT.BORDER); 422 currentSizeField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 423 currentSizeField.setFont(curFont); 424 currentSizeField.setText("1"); 425 426 maxSizeField = new Text(dataspaceGroup, SWT.SINGLE | SWT.BORDER); 427 maxSizeField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 428 maxSizeField.setFont(curFont); 429 maxSizeField.setText("0"); 430 431 432 // Create Data Layout/Compression region 433 org.eclipse.swt.widgets.Group layoutGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE); 434 layoutGroup.setLayout(new GridLayout(7, false)); 435 layoutGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 436 layoutGroup.setFont(curFont); 437 layoutGroup.setText("Data Layout and Compression"); 438 439 label = new Label(layoutGroup, SWT.LEFT); 440 label.setFont(curFont); 441 label.setText("Storage layout: "); 442 443 checkContiguous = new Button(layoutGroup, SWT.RADIO); 444 checkContiguous.setFont(curFont); 445 checkContiguous.setText("Contiguous"); 446 checkContiguous.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 447 checkContiguous.addSelectionListener(new SelectionAdapter() { 448 @Override 449 public void widgetSelected(SelectionEvent e) { 450 chunkSizeField.setEnabled(false); 451 } 452 }); 453 454 // Dummy labels 455 label = new Label(layoutGroup, SWT.LEFT); 456 label.setFont(curFont); 457 label.setText(""); 458 label = new Label(layoutGroup, SWT.LEFT); 459 label.setFont(curFont); 460 label.setText(""); 461 462 checkChunked = new Button(layoutGroup, SWT.RADIO); 463 checkChunked.setFont(curFont); 464 checkChunked.setText("Chunked"); 465 checkChunked.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 466 checkChunked.addSelectionListener(new SelectionAdapter() { 467 @Override 468 public void widgetSelected(SelectionEvent e) { 469 chunkSizeField.setEnabled(true); 470 471 String currentStr = currentSizeField.getText(); 472 int idx = currentStr.lastIndexOf('x'); 473 String chunkStr = "1"; 474 475 int rank = rankChoice.getSelectionIndex() + 1; 476 if (rank <= 1) { 477 chunkStr = currentStr; 478 } 479 else { 480 for (int i = 1; i < rank - 1; i++) { 481 chunkStr += " x 1"; 482 } 483 if (idx > 0) { 484 chunkStr += " x " + currentStr.substring(idx + 1); 485 } 486 } 487 488 chunkSizeField.setText(chunkStr); 489 } 490 }); 491 492 label = new Label(layoutGroup, SWT.LEFT); 493 label.setFont(curFont); 494 label.setText("Size: "); 495 496 chunkSizeField = new Text(layoutGroup, SWT.SINGLE | SWT.BORDER); 497 chunkSizeField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 498 chunkSizeField.setFont(curFont); 499 chunkSizeField.setText("1"); 500 chunkSizeField.setEnabled(false); 501 502 label = new Label(layoutGroup, SWT.LEFT); 503 label.setFont(curFont); 504 label.setText("Compression: "); 505 506 checkCompression = new Button(layoutGroup, SWT.CHECK); 507 checkCompression.setFont(curFont); 508 checkCompression.setText("gzip"); 509 checkCompression.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 510 checkCompression.addSelectionListener(new SelectionAdapter() { 511 @Override 512 public void widgetSelected(SelectionEvent e) { 513 boolean isCompressed = checkCompression.getSelection(); 514 515 if (isCompressed) { 516 if (!checkChunked.getSelection()) { 517 String currentStr = currentSizeField.getText(); 518 int idx = currentStr.lastIndexOf('x'); 519 String chunkStr = "1"; 520 521 int rank = rankChoice.getSelectionIndex() + 1; 522 if (rank <= 1) { 523 chunkStr = currentStr; 524 } 525 else { 526 for (int i = 1; i < rank - 1; i++) { 527 chunkStr += " x 1"; 528 } 529 if (idx > 0) { 530 chunkStr += " x " + currentStr.substring(idx + 1); 531 } 532 } 533 534 chunkSizeField.setText(chunkStr); 535 } 536 537 compressionLevel.setEnabled(true); 538 checkContiguous.setEnabled(false); 539 checkContiguous.setSelection(false); 540 checkChunked.setSelection(true); 541 chunkSizeField.setEnabled(true); 542 } 543 else { 544 compressionLevel.setEnabled(false); 545 checkContiguous.setEnabled(true); 546 } 547 } 548 }); 549 550 label = new Label(layoutGroup, SWT.LEFT); 551 label.setFont(curFont); 552 label.setText("Level: "); 553 554 compressionLevel = new Combo(layoutGroup, SWT.DROP_DOWN | SWT.READ_ONLY); 555 compressionLevel.setFont(curFont); 556 compressionLevel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 557 compressionLevel.setEnabled(false); 558 559 for (int i = 0; i < 10; i++) { 560 compressionLevel.add(String.valueOf(i)); 561 } 562 563 label = new Label(layoutGroup, SWT.LEFT); 564 label.setFont(curFont); 565 label.setText(""); 566 567 label = new Label(layoutGroup, SWT.LEFT); 568 label.setFont(curFont); 569 label.setText(""); 570 571 label = new Label(layoutGroup, SWT.LEFT); 572 label.setFont(curFont); 573 label.setText(""); 574 575 576 // Create Properties region 577 org.eclipse.swt.widgets.Group propertiesGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE); 578 propertiesGroup.setLayout(new GridLayout(2, false)); 579 propertiesGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 580 propertiesGroup.setFont(curFont); 581 propertiesGroup.setText("Compound Datatype Properties"); 582 583 label = new Label(propertiesGroup, SWT.LEFT); 584 label.setFont(curFont); 585 label.setText("Number of Members:"); 586 587 nFieldBox = new Combo(propertiesGroup, SWT.DROP_DOWN); 588 nFieldBox.setFont(curFont); 589 nFieldBox.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 590 nFieldBox.addSelectionListener(new SelectionAdapter() { 591 @Override 592 public void widgetSelected(SelectionEvent e) { 593 updateMemberTableItems(); 594 } 595 }); 596 nFieldBox.addTraverseListener(new TraverseListener() { 597 @Override 598 public void keyTraversed(TraverseEvent e) { 599 if (e.detail == SWT.TRAVERSE_RETURN) updateMemberTableItems(); 600 } 601 }); 602 603 for (int i = 1; i <= 100; i++) { 604 nFieldBox.add(String.valueOf(i)); 605 } 606 607 table = new Table(propertiesGroup, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); 608 table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); 609 table.setLinesVisible(false); 610 table.setHeaderVisible(true); 611 table.setFont(curFont); 612 613 editors = new TableEditor[nFieldBox.getItemCount()][3]; 614 615 String[] colNames = { "Name", "Datatype", "Array size / String length / Enum names" }; 616 617 TableColumn column = new TableColumn(table, SWT.NONE); 618 column.setText(colNames[0]); 619 620 column = new TableColumn(table, SWT.NONE); 621 column.setText(colNames[1]); 622 623 column = new TableColumn(table, SWT.NONE); 624 column.setText(colNames[2]); 625 626 for (int i = 0; i < 2; i++) { 627 TableEditor[] editor = addMemberTableItem(table); 628 editors[i][0] = editor[0]; 629 editors[i][1] = editor[1]; 630 editors[i][2] = editor[2]; 631 } 632 633 for(int i = 0; i < table.getColumnCount(); i++) { 634 table.getColumn(i).pack(); 635 } 636 637 // Last table column always expands to fill remaining table size 638 table.addListener(SWT.Resize, new Listener() { 639 @Override 640 public void handleEvent(Event e) { 641 Table table = (Table) e.widget; 642 Rectangle area = table.getClientArea(); 643 int columnCount = table.getColumnCount(); 644 int totalGridLineWidth = (columnCount - 1) * table.getGridLineWidth(); 645 646 int totalColumnWidth = 0; 647 for (TableColumn column : table.getColumns()) { 648 totalColumnWidth += column.getWidth(); 649 } 650 651 int diff = area.width - (totalColumnWidth + totalGridLineWidth); 652 653 TableColumn col = table.getColumns()[columnCount - 1]; 654 col.setWidth(diff + col.getWidth()); 655 } 656 }); 657 658 // Disable table selection highlighting 659 table.addListener(SWT.EraseItem, new Listener() { 660 @Override 661 public void handleEvent(Event e) { 662 if ((e.detail & SWT.SELECTED) != 0) { 663 e.detail &= ~SWT.SELECTED; 664 } 665 } 666 }); 667 668 // Create Ok/Cancel button region 669 Composite buttonComposite = new Composite(shell, SWT.NONE); 670 buttonComposite.setLayout(new GridLayout(2, true)); 671 buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); 672 673 Button okButton = new Button(buttonComposite, SWT.PUSH); 674 okButton.setFont(curFont); 675 okButton.setText(" &OK "); 676 okButton.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); 677 okButton.addSelectionListener(new SelectionAdapter() { 678 @Override 679 public void widgetSelected(SelectionEvent e) { 680 try { 681 newObject = createCompoundDS(); 682 } 683 catch (Exception ex) { 684 Tools.showError(shell, "Create", ex.getMessage()); 685 } 686 687 if (newObject != null) { 688 shell.dispose(); 689 } 690 } 691 }); 692 693 Button cancelButton = new Button(buttonComposite, SWT.PUSH); 694 cancelButton.setFont(curFont); 695 cancelButton.setText(" &Cancel "); 696 cancelButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false)); 697 cancelButton.addSelectionListener(new SelectionAdapter() { 698 @Override 699 public void widgetSelected(SelectionEvent e) { 700 newObject = null; 701 shell.dispose(); 702 (groupList).setSize(0); 703 } 704 }); 705 706 templateChoice.deselectAll(); 707 rankChoice.select(0); 708 checkContiguous.setSelection(true); 709 compressionLevel.select(6); 710 nFieldBox.select(nFieldBox.indexOf(String.valueOf(numberOfMembers))); 711 712 shell.pack(); 713 714 table.getColumn(0).setWidth(table.getClientArea().width / 3); 715 table.getColumn(1).setWidth(table.getClientArea().width / 3); 716 717 shell.addDisposeListener(new DisposeListener() { 718 @Override 719 public void widgetDisposed(DisposeEvent e) { 720 if (curFont != null) curFont.dispose(); 721 } 722 }); 723 724 shell.setMinimumSize(shell.computeSize(SWT.DEFAULT, SWT.DEFAULT)); 725 726 Rectangle parentBounds = parent.getBounds(); 727 Point shellSize = shell.getSize(); 728 shell.setLocation((parentBounds.x + (parentBounds.width / 2)) - (shellSize.x / 2), 729 (parentBounds.y + (parentBounds.height / 2)) - (shellSize.y / 2)); 730 731 shell.open(); 732 733 Display display = shell.getDisplay(); 734 while (!shell.isDisposed()) 735 if (!display.readAndDispatch()) 736 display.sleep(); 737 } 738 739 private HObject createCompoundDS() throws Exception { 740 HObject obj = null; 741 long dims[], maxdims[], chunks[]; 742 int rank; 743 744 maxdims = chunks = null; 745 String dname = nameField.getText(); 746 if ((dname == null) || (dname.length() <= 0)) { 747 throw new IllegalArgumentException("Dataset name is empty"); 748 } 749 750 Group pgroup = groupList.get(parentChoice.getSelectionIndex()); 751 if (pgroup == null) { 752 throw new IllegalArgumentException("Invalid parent group"); 753 } 754 755 int n = table.getItemCount(); 756 if (n <= 0) { 757 return null; 758 } 759 760 String[] mNames = new String[n]; 761 Datatype[] mDatatypes = new Datatype[n]; 762 int[] mOrders = new int[n]; 763 764 for (int i = 0; i < n; i++) { 765 String name = (String) table.getItem(i).getData("MemberName"); 766 if ((name == null) || (name.length() <= 0)) { 767 throw new IllegalArgumentException("Member name is empty"); 768 } 769 mNames[i] = name; 770 log.trace("createCompoundDS member[{}] name = {}", i, mNames[i]); 771 772 int order = 1; 773 String orderStr = (String) table.getItem(i).getData("MemberSize"); 774 if (orderStr != null) { 775 try { 776 order = Integer.parseInt(orderStr); 777 } 778 catch (Exception ex) { 779 log.debug("compound order:", ex); 780 } 781 } 782 mOrders[i] = order; 783 784 String typeName = (String) table.getItem(i).getData("MemberType"); 785 log.trace("createCompoundDS type[{}] name = {}", i, typeName); 786 Datatype type = null; 787 if (DATATYPE_NAMES[0].equals(typeName)) { 788 type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 1, Datatype.NATIVE, Datatype.NATIVE); 789 } 790 else if (DATATYPE_NAMES[1].equals(typeName)) { 791 type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 2, Datatype.NATIVE, Datatype.NATIVE); 792 } 793 else if (DATATYPE_NAMES[2].equals(typeName)) { 794 type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 4, Datatype.NATIVE, Datatype.NATIVE); 795 } 796 else if (DATATYPE_NAMES[3].equals(typeName)) { 797 type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 1, Datatype.NATIVE, Datatype.SIGN_NONE); 798 } 799 else if (DATATYPE_NAMES[4].equals(typeName)) { 800 type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 2, Datatype.NATIVE, Datatype.SIGN_NONE); 801 } 802 else if (DATATYPE_NAMES[5].equals(typeName)) { 803 type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 4, Datatype.NATIVE, Datatype.SIGN_NONE); 804 } 805 else if (DATATYPE_NAMES[6].equals(typeName)) { 806 type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 8, Datatype.NATIVE, Datatype.NATIVE); 807 } 808 else if (DATATYPE_NAMES[7].equals(typeName)) { 809 type = fileFormat.createDatatype(Datatype.CLASS_FLOAT, 4, Datatype.NATIVE, Datatype.NATIVE); 810 } 811 else if (DATATYPE_NAMES[8].equals(typeName)) { 812 type = fileFormat.createDatatype(Datatype.CLASS_FLOAT, 8, Datatype.NATIVE, Datatype.NATIVE); 813 } 814 else if (DATATYPE_NAMES[9].equals(typeName)) { 815 type = fileFormat.createDatatype(Datatype.CLASS_STRING, order, Datatype.NATIVE, Datatype.NATIVE); 816 } 817 else if (DATATYPE_NAMES[10].equals(typeName)) { // enum 818 type = fileFormat.createDatatype(Datatype.CLASS_ENUM, 4, Datatype.NATIVE, Datatype.NATIVE); 819 if ((orderStr == null) || (orderStr.length() < 1) || orderStr.endsWith("...")) { 820 shell.getDisplay().beep(); 821 Tools.showError(shell, "Create", "Invalid member values: " + orderStr); 822 return null; 823 } 824 else { 825 type.setEnumMembers(orderStr); 826 } 827 } 828 else if (DATATYPE_NAMES[11].equals(typeName)) { 829 type = fileFormat.createDatatype(Datatype.CLASS_INTEGER, 8, Datatype.NATIVE, Datatype.SIGN_NONE); 830 } 831 else { 832 throw new IllegalArgumentException("Invalid data type."); 833 } 834 mDatatypes[i] = type; 835 } // (int i=0; i<n; i++) 836 837 rank = rankChoice.getSelectionIndex() + 1; 838 log.trace("createCompoundDS rank={}", rank); 839 StringTokenizer st = new StringTokenizer(currentSizeField.getText(), "x"); 840 if (st.countTokens() < rank) { 841 shell.getDisplay().beep(); 842 Tools.showError(shell, "Create", "Number of values in the current dimension size is less than " + rank); 843 return null; 844 } 845 846 long l = 0; 847 dims = new long[rank]; 848 String token = null; 849 for (int i = 0; i < rank; i++) { 850 token = st.nextToken().trim(); 851 try { 852 l = Long.parseLong(token); 853 } 854 catch (NumberFormatException ex) { 855 shell.getDisplay().beep(); 856 Tools.showError(shell, "Create", "Invalid dimension size: " + currentSizeField.getText()); 857 return null; 858 } 859 860 if (l <= 0) { 861 shell.getDisplay().beep(); 862 Tools.showError(shell, "Create", "Dimension size must be greater than zero."); 863 return null; 864 } 865 866 dims[i] = l; 867 } 868 869 st = new StringTokenizer(maxSizeField.getText(), "x"); 870 if (st.countTokens() < rank) { 871 shell.getDisplay().beep(); 872 Tools.showError(shell, "Create", "Number of values in the max dimension size is less than " + rank); 873 return null; 874 } 875 876 l = 0; 877 maxdims = new long[rank]; 878 for (int i = 0; i < rank; i++) { 879 token = st.nextToken().trim(); 880 try { 881 l = Long.parseLong(token); 882 } 883 catch (NumberFormatException ex) { 884 shell.getDisplay().beep(); 885 Tools.showError(shell, "Create", "Invalid max dimension size: " + maxSizeField.getText()); 886 return null; 887 } 888 889 if (l < -1) { 890 shell.getDisplay().beep(); 891 Tools.showError(shell, "Create", "Dimension size cannot be less than -1."); 892 return null; 893 } 894 else if (l == 0) { 895 l = dims[i]; 896 } 897 898 maxdims[i] = l; 899 } 900 901 chunks = null; 902 if (checkChunked.getSelection()) { 903 st = new StringTokenizer(chunkSizeField.getText(), "x"); 904 if (st.countTokens() < rank) { 905 shell.getDisplay().beep(); 906 Tools.showError(shell, "Create", "Number of values in the chunk size is less than " + rank); 907 return null; 908 } 909 910 l = 0; 911 chunks = new long[rank]; 912 token = null; 913 for (int i = 0; i < rank; i++) { 914 token = st.nextToken().trim(); 915 try { 916 l = Long.parseLong(token); 917 } 918 catch (NumberFormatException ex) { 919 shell.getDisplay().beep(); 920 Tools.showError(shell, "Create", "Invalid chunk dimension size: " + chunkSizeField.getText()); 921 return null; 922 } 923 924 if (l < 1) { 925 shell.getDisplay().beep(); 926 Tools.showError(shell, "Create", "Chunk size cannot be less than 1."); 927 return null; 928 } 929 930 chunks[i] = l; 931 } // (int i=0; i<rank; i++) 932 933 long tchunksize = 1, tdimsize = 1; 934 for (int i = 0; i < rank; i++) { 935 tchunksize *= chunks[i]; 936 tdimsize *= dims[i]; 937 } 938 939 if (tchunksize >= tdimsize) { 940 shell.getDisplay().beep(); 941 if(!Tools.showConfirm(shell, "Create", "Chunk size is equal/greater than the current size. " 942 + "\nAre you sure you want to set chunk size to " + chunkSizeField.getText() + "?")) { 943 return null; 944 } 945 } 946 947 if (tchunksize == 1) { 948 shell.getDisplay().beep(); 949 if(!Tools.showConfirm(shell, "Create", "Chunk size is one, which may cause large memory overhead for large dataset." 950 + "\nAre you sure you want to set chunk size to " + chunkSizeField.getText() + "?")) { 951 return null; 952 } 953 } 954 955 } // (checkChunked.getSelection()) 956 957 int gzip = 0; 958 if (checkCompression.getSelection()) { 959 gzip = compressionLevel.getSelectionIndex(); 960 } 961 962 if (checkChunked.getSelection()) { 963 obj = fileFormat.createCompoundDS(dname, pgroup, dims, maxdims, chunks, gzip, mNames, mDatatypes, mOrders, null); 964 } 965 else { 966 obj = fileFormat.createCompoundDS(dname, pgroup, dims, maxdims, null, -1, mNames, mDatatypes, mOrders, null); 967 } 968 return obj; 969 } 970 971 private void updateMemberTableItems() { 972 int n = 0; 973 974 try { 975 n = Integer.valueOf(nFieldBox.getItem(nFieldBox.getSelectionIndex())).intValue(); 976 } 977 catch (Exception ex) { 978 log.debug("Change number of members:", ex); 979 return; 980 } 981 982 if (n == numberOfMembers) { 983 return; 984 } 985 986 if(n > numberOfMembers) { 987 try { 988 for (int i = numberOfMembers; i < n; i++) { 989 TableEditor[] editor = addMemberTableItem(table); 990 editors[i][0] = editor[0]; 991 editors[i][1] = editor[1]; 992 editors[i][2] = editor[2]; 993 } 994 } 995 catch (Exception ex) { 996 log.debug("Error adding member table items: ", ex); 997 return; 998 } 999 } else { 1000 try { 1001 for(int i = numberOfMembers - 1; i >= n; i--) { 1002 table.remove(i); 1003 } 1004 } 1005 catch (Exception ex) { 1006 log.debug("Error removing member table items: ", ex); 1007 return; 1008 } 1009 } 1010 1011 table.setItemCount(n); 1012 numberOfMembers = n; 1013 } 1014 1015 private TableEditor[] addMemberTableItem(Table table) { 1016 final TableItem item = new TableItem(table, SWT.NONE); 1017 final TableEditor[] editor = new TableEditor[3]; 1018 1019 for (int i = 0; i < editor.length; i++) editor[i] = new TableEditor(table); 1020 1021 final Text nameText = new Text(table, SWT.SINGLE | SWT.BORDER); 1022 nameText.setFont(curFont); 1023 1024 editor[0].grabHorizontal = true; 1025 editor[0].grabVertical = true; 1026 editor[0].horizontalAlignment = SWT.LEFT; 1027 editor[0].verticalAlignment = SWT.TOP; 1028 editor[0].setEditor(nameText, item, 0); 1029 1030 nameText.addModifyListener(new ModifyListener() { 1031 @Override 1032 public void modifyText(ModifyEvent e) { 1033 Text text = (Text) e.widget; 1034 item.setData("MemberName", text.getText()); 1035 } 1036 }); 1037 1038 final CCombo typeCombo = new CCombo(table, SWT.DROP_DOWN | SWT.READ_ONLY); 1039 typeCombo.setFont(curFont); 1040 typeCombo.setItems(DATATYPE_NAMES); 1041 1042 editor[1].grabHorizontal = true; 1043 editor[1].grabVertical = true; 1044 editor[1].horizontalAlignment = SWT.LEFT; 1045 editor[1].verticalAlignment = SWT.TOP; 1046 editor[1].setEditor(typeCombo, item, 1); 1047 1048 typeCombo.addSelectionListener(new SelectionAdapter() { 1049 @Override 1050 public void widgetSelected(SelectionEvent e) { 1051 CCombo combo = (CCombo) e.widget; 1052 item.setData("MemberType", combo.getItem(combo.getSelectionIndex())); 1053 } 1054 }); 1055 1056 final Text sizeText = new Text(table, SWT.SINGLE | SWT.BORDER); 1057 sizeText.setFont(curFont); 1058 1059 editor[2].grabHorizontal = true; 1060 editor[2].grabVertical = true; 1061 editor[2].horizontalAlignment = SWT.LEFT; 1062 editor[2].verticalAlignment = SWT.TOP; 1063 editor[2].setEditor(sizeText, item, 2); 1064 1065 sizeText.addModifyListener(new ModifyListener() { 1066 @Override 1067 public void modifyText(ModifyEvent e) { 1068 Text text = (Text) e.widget; 1069 item.setData("MemberSize", text.getText()); 1070 } 1071 }); 1072 1073 item.setData("MemberName", ""); 1074 item.setData("MemberType", ""); 1075 item.setData("MemberSize", ""); 1076 1077 item.addDisposeListener(new DisposeListener() { 1078 @Override 1079 public void widgetDisposed(DisposeEvent e) { 1080 editor[0].dispose(); 1081 editor[1].dispose(); 1082 editor[2].dispose(); 1083 nameText.dispose(); 1084 typeCombo.dispose(); 1085 sizeText.dispose(); 1086 } 1087 }); 1088 1089 return editor; 1090 } 1091}