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 http://hdfgroup.org/products/hdf-java/doc/Copyright.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; 016 017import java.awt.BorderLayout; 018import java.awt.Color; 019import java.awt.Dimension; 020import java.awt.GridLayout; 021import java.awt.Point; 022import java.awt.Toolkit; 023import java.awt.event.ActionEvent; 024import java.awt.event.ActionListener; 025import java.awt.event.ItemEvent; 026import java.awt.event.ItemListener; 027import java.awt.event.KeyEvent; 028import java.net.URL; 029import java.net.URLClassLoader; 030import java.util.Iterator; 031import java.util.List; 032import java.util.StringTokenizer; 033import java.util.Vector; 034 035import javax.swing.BorderFactory; 036import javax.swing.ButtonGroup; 037import javax.swing.JButton; 038import javax.swing.JCheckBox; 039import javax.swing.JComboBox; 040import javax.swing.JDialog; 041import javax.swing.JEditorPane; 042import javax.swing.JFrame; 043import javax.swing.JLabel; 044import javax.swing.JOptionPane; 045import javax.swing.JPanel; 046import javax.swing.JRadioButton; 047import javax.swing.JScrollPane; 048import javax.swing.JTextField; 049import javax.swing.border.TitledBorder; 050import javax.swing.event.HyperlinkEvent; 051import javax.swing.event.HyperlinkListener; 052import javax.swing.text.html.HTMLDocument; 053import javax.swing.text.html.HTMLFrameHyperlinkEvent; 054 055import hdf.object.DataFormat; 056import hdf.object.Dataset; 057import hdf.object.Datatype; 058import hdf.object.FileFormat; 059import hdf.object.Group; 060import hdf.object.HObject; 061import hdf.object.ScalarDS; 062 063/** 064 * NewDatasetDialog shows a message dialog requesting user input for creating a 065 * new HDF4/5 dataset. 066 * 067 * @author Peter X. Cao 068 * @version 2.4 9/6/2007 069 */ 070public class NewDatasetDialog extends JDialog implements ActionListener, ItemListener, HyperlinkListener { 071 private static final long serialVersionUID = 5381164938654184532L; 072 073 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NewDatasetDialog.class); 074 075 private JTextField nameField, currentSizeField, maxSizeField, chunkSizeField, stringLengthField, 076 fillValueField; 077 078 @SuppressWarnings("rawtypes") 079 private JComboBox parentChoice, classChoice, sizeChoice, endianChoice, rankChoice, compressionLevel; 080 081 private JCheckBox checkUnsigned, checkCompression, checkFillValue; 082 083 private JRadioButton checkContinguous, checkChunked; 084 085 private JDialog helpDialog; 086 087 private boolean isH5; 088 089 /** a list of current groups */ 090 private List<Object> groupList; 091 092 private HObject newObject; 093 094 private FileFormat fileFormat; 095 096 private final Toolkit toolkit; 097 098 private final DataView dataView; 099 100 /** 101 * Constructs NewDatasetDialog with specified list of possible parent 102 * groups. 103 * 104 * @param owner 105 * the owner of the input 106 * @param pGroup 107 * the parent group which the new group is added to. 108 * @param objs 109 * the list of all objects. 110 */ 111 @SuppressWarnings({ "rawtypes", "unchecked" }) 112 public NewDatasetDialog(JFrame owner, Group pGroup, List<?> objs) { 113 super(owner, "New Dataset...", true); 114 115 helpDialog = null; 116 newObject = null; 117 dataView = null; 118 119 fileFormat = pGroup.getFileFormat(); 120 toolkit = Toolkit.getDefaultToolkit(); 121 isH5 = pGroup.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5)); 122 123 parentChoice = new JComboBox(); 124 groupList = new Vector<Object>(); 125 Object obj = null; 126 Iterator<?> iterator = objs.iterator(); 127 while (iterator.hasNext()) { 128 obj = iterator.next(); 129 if (obj instanceof Group) { 130 Group g = (Group) obj; 131 groupList.add(obj); 132 if (g.isRoot()) { 133 parentChoice.addItem(HObject.separator); 134 } 135 else { 136 parentChoice.addItem(g.getPath() + g.getName() + HObject.separator); 137 } 138 } 139 } 140 141 if (pGroup.isRoot()) { 142 parentChoice.setSelectedItem(HObject.separator); 143 } 144 else { 145 parentChoice.setSelectedItem(pGroup.getPath() + pGroup.getName() + HObject.separator); 146 } 147 148 JPanel contentPane = (JPanel) getContentPane(); 149 contentPane.setLayout(new BorderLayout(5, 5)); 150 contentPane.setBorder(BorderFactory.createEmptyBorder(15, 5, 5, 5)); 151 int w = 600 + (ViewProperties.getFontSize() - 12) * 15; 152 int h = 350 + (ViewProperties.getFontSize() - 12) * 10; 153 contentPane.setPreferredSize(new Dimension(w, h)); 154 155 JButton okButton = new JButton(" Ok "); 156 okButton.setName("OK"); 157 okButton.setActionCommand("Ok"); 158 okButton.setMnemonic(KeyEvent.VK_O); 159 okButton.addActionListener(this); 160 161 JButton cancelButton = new JButton("Cancel"); 162 cancelButton.setName("Cancel"); 163 cancelButton.setMnemonic(KeyEvent.VK_C); 164 cancelButton.setActionCommand("Cancel"); 165 cancelButton.addActionListener(this); 166 167 JButton helplButton = new JButton("Help"); 168 helplButton.setName("Help"); 169 helplButton.setMnemonic(KeyEvent.VK_H); 170 helplButton.setActionCommand("Show help"); 171 helplButton.addActionListener(this); 172 173 // set OK and CANCEL buttons 174 JPanel buttonPanel = new JPanel(); 175 buttonPanel.add(okButton); 176 buttonPanel.add(cancelButton); 177 buttonPanel.add(helplButton); 178 contentPane.add(buttonPanel, BorderLayout.SOUTH); 179 180 // set NAME and PARENT GROUP panel 181 JPanel namePanel = new JPanel(); 182 namePanel.setLayout(new BorderLayout(5, 5)); 183 JPanel tmpP = new JPanel(); 184 tmpP.setLayout(new GridLayout(2, 1)); 185 tmpP.add(new JLabel("Dataset name: ")); 186 tmpP.add(new JLabel("Parent group: ")); 187 namePanel.add(tmpP, BorderLayout.WEST); 188 tmpP = new JPanel(); 189 tmpP.setLayout(new GridLayout(2, 1)); 190 tmpP.add(nameField = new JTextField()); 191 nameField.setName("datasetname"); 192 tmpP.add(parentChoice); 193 namePanel.add(tmpP, BorderLayout.CENTER); 194 contentPane.add(namePanel, BorderLayout.NORTH); 195 196 // set DATATYPE 197 JPanel typePanel = new JPanel(); 198 typePanel.setLayout(new GridLayout(2, 4, 15, 3)); 199 TitledBorder border = new TitledBorder("Datatype"); 200 border.setTitleColor(Color.gray); 201 typePanel.setBorder(border); 202 203 stringLengthField = new JTextField("String length"); 204 stringLengthField.setName("datasetstringlen"); 205 stringLengthField.setEnabled(false); 206 207 endianChoice = new JComboBox(); 208 endianChoice.setName("datasetendian"); 209 classChoice = new JComboBox(); 210 classChoice.setName("datasetclass"); 211 sizeChoice = new JComboBox(); 212 sizeChoice.setName("datasetsize"); 213 endianChoice.setEnabled(isH5); 214 215 classChoice.addItem("INTEGER"); 216 classChoice.addItem("FLOAT"); 217 classChoice.addItem("CHAR"); 218 219 if (isH5) { 220 classChoice.addItem("STRING"); 221 classChoice.addItem("REFERENCE"); 222 classChoice.addItem("ENUM"); 223 classChoice.addItem("VLEN_INTEGER"); 224 classChoice.addItem("VLEN_FLOAT"); 225 classChoice.addItem("VLEN_STRING"); 226 sizeChoice.addItem("NATIVE"); 227 endianChoice.addItem("NATIVE"); 228 endianChoice.addItem("LITTLE ENDIAN"); 229 endianChoice.addItem("BIG ENDIAN"); 230 } 231 else { 232 sizeChoice.addItem("DEFAULT"); 233 endianChoice.addItem("DEFAULT"); 234 } 235 sizeChoice.addItem("8"); 236 sizeChoice.addItem("16"); 237 sizeChoice.addItem("32"); 238 sizeChoice.addItem("64"); 239 240 typePanel.add(new JLabel("Datatype class")); 241 typePanel.add(new JLabel("Size (bits)")); 242 typePanel.add(new JLabel("Byte ordering")); 243 checkUnsigned = new JCheckBox("Unsigned"); 244 checkUnsigned.setName("datasetchkunsigned"); 245 typePanel.add(checkUnsigned); 246 247 typePanel.add(classChoice); 248 typePanel.add(sizeChoice); 249 typePanel.add(endianChoice); 250 typePanel.add(stringLengthField); 251 252 // set DATATSPACE 253 JPanel spacePanel = new JPanel(); 254 spacePanel.setLayout(new GridLayout(2, 3, 15, 3)); 255 border = new TitledBorder("Dataspace"); 256 border.setTitleColor(Color.gray); 257 spacePanel.setBorder(border); 258 259 rankChoice = new JComboBox(); 260 rankChoice.setName("datasetrank"); 261 for (int i = 1; i < 33; i++) { 262 rankChoice.addItem(String.valueOf(i)); 263 } 264 rankChoice.setSelectedIndex(1); 265 266 currentSizeField = new JTextField("1 x 1"); 267 currentSizeField.setName("currentsize"); 268 maxSizeField = new JTextField(""); 269 spacePanel.add(new JLabel("No. of dimensions")); 270 spacePanel.add(new JLabel("Current size")); 271 spacePanel.add(new JLabel("")); 272 spacePanel.add(rankChoice); 273 spacePanel.add(currentSizeField); 274 JButton jb = new JButton("Set Max Size"); 275 jb.setActionCommand("Set max size"); 276 jb.addActionListener(this); 277 spacePanel.add(jb); 278 // spacePanel.add(maxSizeField); 279 280 // set storage layout and data compression 281 JPanel layoutPanel = new JPanel(); 282 layoutPanel.setLayout(new BorderLayout()); 283 border = new TitledBorder("Storage Properties"); 284 border.setTitleColor(Color.gray); 285 layoutPanel.setBorder(border); 286 287 checkContinguous = new JRadioButton("Contiguous"); 288 checkContinguous.setName("datasetcontinguous"); 289 checkContinguous.setSelected(true); 290 checkChunked = new JRadioButton("Chunked (size) "); 291 checkChunked.setName("datasetchunk"); 292 ButtonGroup bgroup = new ButtonGroup(); 293 bgroup.add(checkChunked); 294 bgroup.add(checkContinguous); 295 chunkSizeField = new JTextField("1 x 1"); 296 chunkSizeField.setName("datasetchunksize"); 297 chunkSizeField.setEnabled(false); 298 checkCompression = new JCheckBox("gzip (level) "); 299 checkCompression.setName("datasetgzip"); 300 301 compressionLevel = new JComboBox(); 302 compressionLevel.setName("datasetlevel"); 303 for (int i = 0; i < 10; i++) { 304 compressionLevel.addItem(String.valueOf(i)); 305 } 306 compressionLevel.setSelectedIndex(6); 307 compressionLevel.setEnabled(false); 308 309 tmpP = new JPanel(); 310 tmpP.setLayout(new GridLayout(2, 1)); 311 tmpP.add(new JLabel("Storage layout: ")); 312 tmpP.add(new JLabel("Compression: ")); 313 layoutPanel.add(tmpP, BorderLayout.WEST); 314 315 tmpP = new JPanel(); 316 tmpP.setLayout(new GridLayout(2, 1)); 317 318 // storage layout 319 JPanel tmpP0 = new JPanel(); 320 tmpP0.setLayout(new GridLayout(1, 3, 0, 5)); 321 tmpP0.add(checkContinguous); 322 JPanel tmpP00 = new JPanel(); 323 tmpP00.setLayout(new BorderLayout()); 324 tmpP00.add(checkChunked, BorderLayout.WEST); 325 tmpP00.add(chunkSizeField, BorderLayout.CENTER); 326 tmpP0.add(tmpP00); 327 tmpP0.add(new JLabel("")); 328 tmpP.add(tmpP0); 329 330 tmpP0 = new JPanel(); 331 tmpP0.setLayout(new GridLayout(1, 2, 30, 5)); 332 333 // compression 334 tmpP00 = new JPanel(); 335 tmpP00.setLayout(new BorderLayout()); 336 tmpP00.add(checkCompression, BorderLayout.WEST); 337 tmpP00.add(compressionLevel, BorderLayout.CENTER); 338 tmpP0.add(tmpP00); 339 340 // fill values 341 checkFillValue = new JCheckBox("Fill Value "); 342 checkFillValue.setName("datasetchkfill"); 343 fillValueField = new JTextField("0"); 344 fillValueField.setName("datasetfillval"); 345 fillValueField.setEnabled(false); 346 checkFillValue.setSelected(false); 347 tmpP00 = new JPanel(); 348 tmpP00.setLayout(new BorderLayout()); 349 tmpP00.add(checkFillValue, BorderLayout.WEST); 350 tmpP00.add(fillValueField, BorderLayout.CENTER); 351 352 if (isH5) 353 tmpP0.add(tmpP00); 354 else 355 tmpP0.add(new JLabel("")); 356 357 tmpP.add(tmpP0); 358 359 layoutPanel.add(tmpP, BorderLayout.CENTER); 360 361 JPanel infoPanel = new JPanel(); 362 infoPanel.setLayout(new GridLayout(3, 1, 5, 10)); 363 infoPanel.add(typePanel); 364 infoPanel.add(spacePanel); 365 infoPanel.add(layoutPanel); 366 contentPane.add(infoPanel, BorderLayout.CENTER); 367 368 classChoice.addItemListener(this); 369 sizeChoice.addItemListener(this); 370 rankChoice.addItemListener(this); 371 checkCompression.addItemListener(this); 372 checkFillValue.addItemListener(this); 373 checkContinguous.addItemListener(this); 374 checkChunked.addItemListener(this); 375 376 // locate the H5Property dialog 377 Point l = owner.getLocation(); 378 l.x += 250; 379 l.y += 80; 380 setLocation(l); 381 validate(); 382 pack(); 383 } 384 385 /** 386 * Constructs NewDatasetDialog with specified list of possible parent 387 * groups. 388 * 389 * @param owner 390 * the owner of the input 391 * @param pGroup 392 * the parent group which the new group is added to. 393 * @param objs 394 * the list of all objects. 395 */ 396 @SuppressWarnings({ "rawtypes", "unchecked" }) 397 public NewDatasetDialog(JFrame owner, Group pGroup, List<?> objs, DataView observer) { 398 super(owner, "New Dataset...", true); 399 400 helpDialog = null; 401 newObject = null; 402 dataView = observer; 403 404 fileFormat = pGroup.getFileFormat(); 405 toolkit = Toolkit.getDefaultToolkit(); 406 isH5 = pGroup.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5)); 407 408 parentChoice = new JComboBox(); 409 groupList = new Vector<Object>(); 410 Object obj = null; 411 Iterator<?> iterator = objs.iterator(); 412 while (iterator.hasNext()) { 413 obj = iterator.next(); 414 if (obj instanceof Group) { 415 Group g = (Group) obj; 416 groupList.add(obj); 417 if (g.isRoot()) { 418 parentChoice.addItem(HObject.separator); 419 } 420 else { 421 parentChoice.addItem(g.getPath() + g.getName() + HObject.separator); 422 } 423 } 424 } 425 426 if (pGroup.isRoot()) { 427 parentChoice.setSelectedItem(HObject.separator); 428 } 429 else { 430 parentChoice.setSelectedItem(pGroup.getPath() + pGroup.getName() + HObject.separator); 431 } 432 433 JPanel contentPane = (JPanel) getContentPane(); 434 contentPane.setLayout(new BorderLayout(5, 5)); 435 contentPane.setBorder(BorderFactory.createEmptyBorder(15, 5, 5, 5)); 436 int w = 400 + (ViewProperties.getFontSize() - 12) * 15; 437 int h = 120 + (ViewProperties.getFontSize() - 12) * 10; 438 contentPane.setPreferredSize(new Dimension(w, h)); 439 440 JButton okButton = new JButton(" Ok "); 441 okButton.setActionCommand("Ok"); 442 okButton.setMnemonic(KeyEvent.VK_O); 443 okButton.addActionListener(this); 444 445 JButton cancelButton = new JButton("Cancel"); 446 cancelButton.setMnemonic(KeyEvent.VK_C); 447 cancelButton.setActionCommand("Cancel"); 448 cancelButton.addActionListener(this); 449 450 // set OK and CANCEL buttons 451 JPanel buttonPanel = new JPanel(); 452 buttonPanel.add(okButton); 453 buttonPanel.add(cancelButton); 454 contentPane.add(buttonPanel, BorderLayout.SOUTH); 455 456 // set NAME and PARENT GROUP panel 457 JPanel namePanel = new JPanel(); 458 namePanel.setLayout(new BorderLayout(5, 5)); 459 JPanel tmpP = new JPanel(); 460 tmpP.setLayout(new GridLayout(2, 1)); 461 tmpP.add(new JLabel("Dataset name: ")); 462 tmpP.add(new JLabel("Parent group: ")); 463 namePanel.add(tmpP, BorderLayout.WEST); 464 tmpP = new JPanel(); 465 tmpP.setLayout(new GridLayout(2, 1)); 466 tmpP.add(nameField = new JTextField(((HObject) observer.getDataObject()).getName() + "~copy", 40)); 467 tmpP.add(parentChoice); 468 namePanel.add(tmpP, BorderLayout.CENTER); 469 contentPane.add(namePanel, BorderLayout.CENTER); 470 471 // locate the H5Property dialog 472 Point l = owner.getLocation(); 473 l.x += 250; 474 l.y += 80; 475 setLocation(l); 476 pack(); 477 } 478 479 public void actionPerformed(ActionEvent e) { 480 String cmd = e.getActionCommand(); 481 482 if (cmd.equals("Ok")) { 483 if (dataView instanceof TableView) { 484 newObject = createFromTable(); 485 } 486 else if (dataView instanceof ImageView) { 487 newObject = createFromImage(); 488 } 489 else if (dataView == null) { 490 newObject = createFromScratch(); 491 } 492 493 if (newObject != null) { 494 dispose(); 495 } 496 } 497 if (cmd.equals("Cancel")) { 498 newObject = null; 499 dispose(); 500 ((Vector<Object>) groupList).setSize(0); 501 } 502 else if (cmd.equals("Show help")) { 503 if (helpDialog == null) { 504 createHelpDialog(); 505 } 506 helpDialog.setVisible(true); 507 } 508 else if (cmd.equals("Hide help")) { 509 if (helpDialog != null) { 510 helpDialog.setVisible(false); 511 } 512 } 513 else if (cmd.equals("Set max size")) { 514 String strMax = maxSizeField.getText(); 515 if (strMax == null || strMax.length() < 1) strMax = currentSizeField.getText(); 516 517 String msg = JOptionPane.showInputDialog(this, "Enter max dimension sizes. \n" 518 + "Use \"unlimited\" for unlimited dimension size.\n\n" + "For example,\n" + " 200 x 100\n" 519 + " 100 x unlimited\n\n", strMax); 520 521 if (msg == null || msg.length() < 1) 522 maxSizeField.setText(currentSizeField.getText()); 523 else 524 maxSizeField.setText(msg); 525 526 checkMaxSize(); 527 } 528 } 529 530 @SuppressWarnings("unchecked") 531 public void itemStateChanged(ItemEvent e) { 532 Object source = e.getSource(); 533 534 if (source.equals(classChoice)) { 535 int idx = classChoice.getSelectedIndex(); 536 sizeChoice.setSelectedIndex(0); 537 endianChoice.setSelectedIndex(0); 538 stringLengthField.setEnabled(false); 539 540 if ((idx == 0) || (idx == 6)) { // INTEGER 541 sizeChoice.setEnabled(true); 542 endianChoice.setEnabled(isH5); 543 checkUnsigned.setEnabled(true); 544 545 if (sizeChoice.getItemCount() == 3) { 546 sizeChoice.removeItem("32"); 547 sizeChoice.removeItem("64"); 548 sizeChoice.addItem("8"); 549 sizeChoice.addItem("16"); 550 sizeChoice.addItem("32"); 551 sizeChoice.addItem("64"); 552 } 553 } 554 else if ((idx == 1) || (idx == 7)) { // FLOAT 555 sizeChoice.setEnabled(true); 556 endianChoice.setEnabled(isH5); 557 checkUnsigned.setEnabled(false); 558 559 if (sizeChoice.getItemCount() == 5) { 560 sizeChoice.removeItem("16"); 561 sizeChoice.removeItem("8"); 562 } 563 } 564 else if (idx == 2) { // CHAR 565 sizeChoice.setEnabled(false); 566 endianChoice.setEnabled(isH5); 567 checkUnsigned.setEnabled(true); 568 } 569 else if (idx == 3) { // STRING 570 sizeChoice.setEnabled(false); 571 endianChoice.setEnabled(false); 572 checkUnsigned.setEnabled(false); 573 stringLengthField.setEnabled(true); 574 stringLengthField.setText("String length"); 575 } 576 else if (idx == 4) { // REFERENCE 577 sizeChoice.setEnabled(false); 578 endianChoice.setEnabled(false); 579 checkUnsigned.setEnabled(false); 580 stringLengthField.setEnabled(false); 581 } 582 else if (idx == 5) { // ENUM 583 sizeChoice.setEnabled(true); 584 checkUnsigned.setEnabled(true); 585 stringLengthField.setEnabled(true); 586 stringLengthField.setText("R=0,G=1,B=2,..."); 587 } 588 else if (idx == 8) { 589 sizeChoice.setEnabled(false); 590 endianChoice.setEnabled(false); 591 checkUnsigned.setEnabled(false); 592 stringLengthField.setEnabled(false); 593 } 594 } 595 else if (source.equals(sizeChoice)) { 596 if (classChoice.getSelectedIndex() == 0) { 597 checkUnsigned.setEnabled(true); 598 } 599 } 600 else if (source.equals(rankChoice)) { 601 int rank = rankChoice.getSelectedIndex() + 1; 602 String currentSizeStr = "1"; 603 String maxSizeStr = "0"; 604 605 for (int i = 1; i < rank; i++) { 606 currentSizeStr += " x 1"; 607 maxSizeStr += " x 0"; 608 } 609 610 currentSizeField.setText(currentSizeStr); 611 maxSizeField.setText(maxSizeStr); 612 613 String currentStr = currentSizeField.getText(); 614 int idx = currentStr.lastIndexOf("x"); 615 String chunkStr = "1"; 616 617 if (rank <= 1) { 618 chunkStr = currentStr; 619 } 620 else { 621 for (int i = 1; i < rank - 1; i++) { 622 chunkStr += " x 1"; 623 } 624 if (idx > 0) { 625 chunkStr += " x " + currentStr.substring(idx + 1); 626 } 627 } 628 629 chunkSizeField.setText(chunkStr); 630 } 631 else if (source.equals(checkContinguous)) { 632 chunkSizeField.setEnabled(false); 633 } 634 else if (source.equals(checkChunked)) { 635 chunkSizeField.setEnabled(true); 636 String chunkStr = ""; 637 StringTokenizer st = new StringTokenizer(currentSizeField.getText(), "x"); 638 int rank = rankChoice.getSelectedIndex() + 1; 639 while (st.hasMoreTokens()) { 640 long l = Math.max(1, Long.valueOf(st.nextToken().trim()) / (2 * rank)); 641 chunkStr += String.valueOf(l) + "x"; 642 } 643 chunkStr = chunkStr.substring(0, chunkStr.lastIndexOf('x')); 644 chunkSizeField.setText(chunkStr); 645 } 646 else if (source.equals(checkCompression)) { 647 boolean isCompressed = checkCompression.isSelected(); 648 649 if (isCompressed && isH5) { 650 if (!checkChunked.isSelected()) { 651 String currentStr = currentSizeField.getText(); 652 int idx = currentStr.lastIndexOf("x"); 653 String chunkStr = "1"; 654 655 int rank = rankChoice.getSelectedIndex() + 1; 656 if (rank <= 1) { 657 chunkStr = currentStr; 658 } 659 else { 660 for (int i = 1; i < rank - 1; i++) { 661 chunkStr += " x 1"; 662 } 663 if (idx > 0) { 664 chunkStr += " x " + currentStr.substring(idx + 1); 665 } 666 } 667 668 chunkSizeField.setText(chunkStr); 669 } 670 compressionLevel.setEnabled(true); 671 checkContinguous.setEnabled(false); 672 checkChunked.setSelected(true); 673 chunkSizeField.setEnabled(true); 674 } 675 else { 676 compressionLevel.setEnabled(isCompressed); 677 checkContinguous.setEnabled(true); 678 } 679 } 680 else if (source.equals(checkFillValue)) { 681 fillValueField.setEnabled(checkFillValue.isSelected()); 682 } 683 } 684 685 /** check is the max size is valid */ 686 private void checkMaxSize() { 687 boolean isChunkNeeded = false; 688 String dimStr = currentSizeField.getText(); 689 String maxStr = maxSizeField.getText(); 690 StringTokenizer stMax = new StringTokenizer(maxStr, "x"); 691 StringTokenizer stDim = new StringTokenizer(dimStr, "x"); 692 693 if (stMax.countTokens() != stDim.countTokens()) { 694 toolkit.beep(); 695 JOptionPane.showMessageDialog(this, "Wrong number of values in the max dimension size " + maxStr, 696 getTitle(), JOptionPane.ERROR_MESSAGE); 697 maxSizeField.setText(null); 698 return; 699 } 700 701 int rank = stDim.countTokens(); 702 long max = 0, dim = 0; 703 long[] maxdims = new long[rank]; 704 for (int i = 0; i < rank; i++) { 705 String token = stMax.nextToken().trim(); 706 707 token = token.toLowerCase(); 708 if (token.startsWith("u")) { 709 max = -1; 710 isChunkNeeded = true; 711 } 712 else { 713 try { 714 max = Long.parseLong(token); 715 } 716 catch (NumberFormatException ex) { 717 toolkit.beep(); 718 JOptionPane.showMessageDialog(this, "Invalid max dimension size: " + maxStr, getTitle(), 719 JOptionPane.ERROR_MESSAGE); 720 maxSizeField.setText(null); 721 return; 722 } 723 } 724 725 token = stDim.nextToken().trim(); 726 try { 727 dim = Long.parseLong(token); 728 } 729 catch (NumberFormatException ex) { 730 toolkit.beep(); 731 JOptionPane.showMessageDialog(this, "Invalid dimension size: " + dimStr, getTitle(), 732 JOptionPane.ERROR_MESSAGE); 733 return; 734 } 735 736 if (max != -1 && max < dim) { 737 toolkit.beep(); 738 JOptionPane.showMessageDialog(this, "Invalid max dimension size: " + maxStr, getTitle(), 739 JOptionPane.ERROR_MESSAGE); 740 maxSizeField.setText(null); 741 return; 742 } 743 else if (max > dim) { 744 isChunkNeeded = true; 745 } 746 747 maxdims[i] = max; 748 } // for (int i = 0; i < rank; i++) 749 750 if (isH5) { 751 if (isChunkNeeded && !checkChunked.isSelected()) { 752 toolkit.beep(); 753 JOptionPane.showMessageDialog(this, "Chunking is required for the max dimensions of " + maxStr, 754 getTitle(), JOptionPane.ERROR_MESSAGE); 755 checkChunked.setSelected(true); 756 } 757 } 758 else { 759 for (int i = 1; i < rank; i++) { 760 if (maxdims[i] <= 0) { 761 maxSizeField.setText(currentSizeField.getText()); 762 toolkit.beep(); 763 JOptionPane.showMessageDialog(this, "Only dim[0] can be unlimited." + maxStr, getTitle(), 764 JOptionPane.ERROR_MESSAGE); 765 return; 766 } 767 } 768 } 769 } 770 771 /** Creates a dialog to show the help information. */ 772 private void createHelpDialog() { 773 helpDialog = new JDialog(this, "Create New Dataset"); 774 775 JPanel contentPane = (JPanel) helpDialog.getContentPane(); 776 contentPane.setLayout(new BorderLayout(5, 5)); 777 contentPane.setBorder(BorderFactory.createEmptyBorder(15, 5, 5, 5)); 778 int w = 500 + (ViewProperties.getFontSize() - 12) * 15; 779 int h = 400 + (ViewProperties.getFontSize() - 12) * 10; 780 contentPane.setPreferredSize(new Dimension(w, h)); 781 782 JButton b = new JButton(" Ok "); 783 b.addActionListener(this); 784 b.setActionCommand("Hide help"); 785 JPanel tmpP = new JPanel(); 786 tmpP.add(b); 787 contentPane.add(tmpP, BorderLayout.SOUTH); 788 789 JEditorPane infoPane = new JEditorPane(); 790 infoPane.setEditable(false); 791 JScrollPane editorScrollPane = new JScrollPane(infoPane); 792 contentPane.add(editorScrollPane, BorderLayout.CENTER); 793 794 try { 795 URL url = null, url2 = null, url3 = null; 796 String rootPath = ViewProperties.getViewRoot(); 797 798 try { 799 url = new URL("file:" + rootPath + "/lib/jhdfview.jar"); 800 } 801 catch (java.net.MalformedURLException mfu) { 802 log.debug("help information:", mfu); 803 } 804 805 try { 806 url2 = new URL("file:" + rootPath + "/"); 807 } 808 catch (java.net.MalformedURLException mfu) { 809 log.debug("help information:", mfu); 810 } 811 812 try { 813 url3 = new URL("file:" + rootPath + "/src/"); 814 } 815 catch (java.net.MalformedURLException mfu) { 816 log.debug("help information:", mfu); 817 } 818 819 URL uu[] = { url, url2, url3 }; 820 URLClassLoader cl = new URLClassLoader(uu); 821 URL u = cl.findResource("hdf/view/NewDatasetHelp.html"); 822 823 infoPane.setPage(u); 824 infoPane.addHyperlinkListener(this); 825 } 826 catch (Exception e) { 827 infoPane.setContentType("text/html"); 828 StringBuffer buff = new StringBuffer(); 829 buff.append("<html>"); 830 buff.append("<body>"); 831 buff.append("ERROR: cannot load help information."); 832 buff.append("</body>"); 833 buff.append("</html>"); 834 infoPane.setText(buff.toString()); 835 } 836 837 Point l = helpDialog.getOwner().getLocation(); 838 l.x += 50; 839 l.y += 80; 840 helpDialog.setLocation(l); 841 helpDialog.validate(); 842 helpDialog.pack(); 843 } 844 845 public void hyperlinkUpdate(HyperlinkEvent e) { 846 if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { 847 JEditorPane pane = (JEditorPane) e.getSource(); 848 849 if (e instanceof HTMLFrameHyperlinkEvent) { 850 HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) e; 851 HTMLDocument doc = (HTMLDocument) pane.getDocument(); 852 doc.processHTMLFrameHyperlinkEvent(evt); 853 } 854 else { 855 try { 856 pane.setPage(e.getURL()); 857 } 858 catch (Throwable t) { 859 log.debug("JEditorPane hyperlink:", t); 860 } 861 } 862 } 863 } 864 865 private HObject createFromScratch() { 866 String name = null; 867 Group pgroup = null; 868 boolean isVLen = false; 869 int rank = -1, gzip = -1, tclass = -1, tsize = -1, torder = -1, tsign = -1; 870 long dims[], maxdims[] = null, chunks[] = null; 871 872 name = nameField.getText().trim(); 873 if ((name == null) || (name.length() < 1)) { 874 toolkit.beep(); 875 JOptionPane 876 .showMessageDialog(this, "Dataset name is not specified.", getTitle(), JOptionPane.ERROR_MESSAGE); 877 return null; 878 } 879 880 if (name.indexOf(HObject.separator) >= 0) { 881 toolkit.beep(); 882 JOptionPane.showMessageDialog(this, "Dataset name cannot contain path.", getTitle(), 883 JOptionPane.ERROR_MESSAGE); 884 return null; 885 } 886 887 pgroup = (Group) groupList.get(parentChoice.getSelectedIndex()); 888 889 if (pgroup == null) { 890 toolkit.beep(); 891 JOptionPane.showMessageDialog(this, "Parent group is null.", getTitle(), JOptionPane.ERROR_MESSAGE); 892 return null; 893 } 894 895 // set datatype class 896 int idx = classChoice.getSelectedIndex(); 897 if (idx == 0) { 898 tclass = Datatype.CLASS_INTEGER; 899 if (checkUnsigned.isSelected()) { 900 tsign = Datatype.SIGN_NONE; 901 } 902 } 903 else if (idx == 1) { 904 tclass = Datatype.CLASS_FLOAT; 905 } 906 else if (idx == 2) { 907 tclass = Datatype.CLASS_CHAR; 908 if (checkUnsigned.isSelected()) { 909 tsign = Datatype.SIGN_NONE; 910 } 911 } 912 else if (idx == 3) { 913 tclass = Datatype.CLASS_STRING; 914 } 915 else if (idx == 4) { 916 tclass = Datatype.CLASS_REFERENCE; 917 } 918 else if (idx == 5) { 919 tclass = Datatype.CLASS_ENUM; 920 } 921 else if (idx == 6) { 922 isVLen = true; 923 tclass = Datatype.CLASS_INTEGER; 924 if (checkUnsigned.isSelected()) { 925 tsign = Datatype.SIGN_NONE; 926 } 927 } 928 else if (idx == 7) { 929 isVLen = true; 930 tclass = Datatype.CLASS_FLOAT; 931 } 932 else if (idx == 8) { 933 isVLen = true; 934 tclass = Datatype.CLASS_STRING; 935 } 936 937 // set datatype size/order 938 idx = sizeChoice.getSelectedIndex(); 939 if (tclass == Datatype.CLASS_STRING) { 940 if (isVLen) { 941 tsize = -1; 942 } 943 else { 944 int stringLength = 0; 945 try { 946 stringLength = Integer.parseInt(stringLengthField.getText()); 947 } 948 catch (NumberFormatException ex) { 949 stringLength = -1; 950 } 951 952 if (stringLength <= 0) { 953 toolkit.beep(); 954 JOptionPane.showMessageDialog(this, "Invalid string length: " + stringLengthField.getText(), 955 getTitle(), JOptionPane.ERROR_MESSAGE); 956 return null; 957 } 958 tsize = stringLength; 959 } 960 } 961 else if (tclass == Datatype.CLASS_ENUM) { 962 String enumStr = stringLengthField.getText(); 963 if ((enumStr == null) || (enumStr.length() < 1) || enumStr.endsWith("...")) { 964 toolkit.beep(); 965 JOptionPane.showMessageDialog(this, "Invalid member values: " + stringLengthField.getText(), 966 getTitle(), JOptionPane.ERROR_MESSAGE); 967 return null; 968 } 969 } 970 else if (tclass == Datatype.CLASS_REFERENCE) { 971 tsize = 1; 972 } 973 else if (idx == 0) { 974 tsize = Datatype.NATIVE; 975 } 976 else if (tclass == Datatype.CLASS_FLOAT) { 977 tsize = idx * 4; 978 } 979 else { 980 tsize = 1 << (idx - 1); 981 } 982 983 if ((tsize == 8) && !isH5 && (tclass == Datatype.CLASS_INTEGER)) { 984 toolkit.beep(); 985 JOptionPane.showMessageDialog(this, "HDF4 does not support 64-bit integer.", getTitle(), 986 JOptionPane.ERROR_MESSAGE); 987 return null; 988 } 989 990 // set order 991 idx = endianChoice.getSelectedIndex(); 992 if (idx == 0) { 993 torder = Datatype.NATIVE; 994 } 995 else if (idx == 1) { 996 torder = Datatype.ORDER_LE; 997 } 998 else { 999 torder = Datatype.ORDER_BE; 1000 } 1001 1002 rank = rankChoice.getSelectedIndex() + 1; 1003 StringTokenizer st = new StringTokenizer(currentSizeField.getText(), "x"); 1004 if (st.countTokens() < rank) { 1005 toolkit.beep(); 1006 JOptionPane.showMessageDialog(this, "Number of values in the current dimension size is less than " + rank, 1007 getTitle(), JOptionPane.ERROR_MESSAGE); 1008 return null; 1009 } 1010 1011 long l = 0; 1012 dims = new long[rank]; 1013 String token = null; 1014 for (int i = 0; i < rank; i++) { 1015 token = st.nextToken().trim(); 1016 try { 1017 l = Long.parseLong(token); 1018 } 1019 catch (NumberFormatException ex) { 1020 toolkit.beep(); 1021 JOptionPane.showMessageDialog(this, "Invalid dimension size: " + currentSizeField.getText(), 1022 getTitle(), JOptionPane.ERROR_MESSAGE); 1023 return null; 1024 } 1025 1026 if (l <= 0) { 1027 toolkit.beep(); 1028 JOptionPane.showMessageDialog(this, "Dimension size must be greater than zero.", getTitle(), 1029 JOptionPane.ERROR_MESSAGE); 1030 return null; 1031 } 1032 1033 dims[i] = l; 1034 } 1035 1036 String maxFieldStr = maxSizeField.getText(); 1037 if (maxFieldStr != null && maxFieldStr.length() > 1) { 1038 st = new StringTokenizer(maxFieldStr, "x"); 1039 if (st.countTokens() < rank) { 1040 toolkit.beep(); 1041 JOptionPane.showMessageDialog(this, "Number of values in the max dimension size is less than " + rank, 1042 getTitle(), JOptionPane.ERROR_MESSAGE); 1043 return null; 1044 } 1045 1046 l = 0; 1047 maxdims = new long[rank]; 1048 for (int i = 0; i < rank; i++) { 1049 token = st.nextToken().trim(); 1050 1051 token = token.toLowerCase(); 1052 if (token.startsWith("u")) 1053 l = -1; 1054 else { 1055 try { 1056 l = Long.parseLong(token); 1057 } 1058 catch (NumberFormatException ex) { 1059 toolkit.beep(); 1060 JOptionPane.showMessageDialog(this, "Invalid max dimension size: " + maxSizeField.getText(), 1061 getTitle(), JOptionPane.ERROR_MESSAGE); 1062 return null; 1063 } 1064 } 1065 1066 if (l < -1) { 1067 toolkit.beep(); 1068 JOptionPane.showMessageDialog(this, "Dimension size cannot be less than -1.", getTitle(), 1069 JOptionPane.ERROR_MESSAGE); 1070 return null; 1071 } 1072 else if (l == 0) { 1073 l = dims[i]; 1074 } 1075 1076 maxdims[i] = l; 1077 } 1078 } 1079 1080 chunks = null; 1081 if (checkChunked.isSelected()) { 1082 st = new StringTokenizer(chunkSizeField.getText(), "x"); 1083 if (st.countTokens() < rank) { 1084 toolkit.beep(); 1085 JOptionPane.showMessageDialog(this, "Number of values in the chunk size is less than " + rank, 1086 getTitle(), JOptionPane.ERROR_MESSAGE); 1087 return null; 1088 } 1089 1090 l = 0; 1091 chunks = new long[rank]; 1092 for (int i = 0; i < rank; i++) { 1093 token = st.nextToken().trim(); 1094 try { 1095 l = Long.parseLong(token); 1096 } 1097 catch (NumberFormatException ex) { 1098 toolkit.beep(); 1099 JOptionPane.showMessageDialog(this, "Invalid chunk dimension size: " + chunkSizeField.getText(), 1100 getTitle(), JOptionPane.ERROR_MESSAGE); 1101 return null; 1102 } 1103 1104 if (l < 1) { 1105 toolkit.beep(); 1106 JOptionPane.showMessageDialog(this, "Chunk size cannot be less than 1.", getTitle(), 1107 JOptionPane.ERROR_MESSAGE); 1108 return null; 1109 } 1110 1111 chunks[i] = l; 1112 } // for (int i=0; i<rank; i++) 1113 1114 long tchunksize = 1, tdimsize = 1; 1115 for (int i = 0; i < rank; i++) { 1116 tchunksize *= chunks[i]; 1117 tdimsize *= dims[i]; 1118 } 1119 1120 if (tchunksize >= tdimsize) { 1121 toolkit.beep(); 1122 int status = JOptionPane.showConfirmDialog(this, "Chunk size is equal/greater than the current size. " 1123 + "\nAre you sure you want to set chunk size to " + chunkSizeField.getText() + "?", getTitle(), 1124 JOptionPane.YES_NO_OPTION); 1125 if (status == JOptionPane.NO_OPTION) { 1126 return null; 1127 } 1128 } 1129 1130 if (tchunksize == 1) { 1131 toolkit.beep(); 1132 int status = JOptionPane.showConfirmDialog(this, 1133 "Chunk size is one, which may cause large memory overhead for large dataset." 1134 + "\nAre you sure you want to set chunk size to " + chunkSizeField.getText() + "?", 1135 getTitle(), JOptionPane.YES_NO_OPTION); 1136 if (status == JOptionPane.NO_OPTION) { 1137 return null; 1138 } 1139 } 1140 1141 } // if (checkChunked.isSelected()) 1142 1143 if (checkCompression.isSelected()) { 1144 gzip = compressionLevel.getSelectedIndex(); 1145 } 1146 else { 1147 gzip = 0; 1148 } 1149 1150 HObject obj = null; 1151 try { 1152 Datatype basedatatype = null; 1153 if (isVLen) { 1154 basedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign); 1155 tclass = Datatype.CLASS_VLEN; 1156 } 1157 Datatype datatype = fileFormat.createDatatype(tclass, tsize, torder, tsign, basedatatype); 1158 if (tclass == Datatype.CLASS_ENUM) { 1159 datatype.setEnumMembers(stringLengthField.getText()); 1160 } 1161 String fillValue = null; 1162 if (fillValueField.isEnabled()) fillValue = fillValueField.getText(); 1163 1164 obj = fileFormat.createScalarDS(name, pgroup, datatype, dims, maxdims, chunks, gzip, fillValue, null); 1165 } 1166 catch (Exception ex) { 1167 toolkit.beep(); 1168 JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE); 1169 return null; 1170 } 1171 1172 return obj; 1173 } 1174 1175 private HObject createFromTable() { 1176 HObject obj = null; 1177 1178 String name = null; 1179 Group pgroup = null; 1180 1181 name = nameField.getText(); 1182 if (name == null) { 1183 toolkit.beep(); 1184 JOptionPane 1185 .showMessageDialog(this, "Dataset name is not specified.", getTitle(), JOptionPane.ERROR_MESSAGE); 1186 return null; 1187 } 1188 1189 if (name.indexOf(HObject.separator) >= 0) { 1190 toolkit.beep(); 1191 JOptionPane.showMessageDialog(this, "Dataset name cannot contain path.", getTitle(), 1192 JOptionPane.ERROR_MESSAGE); 1193 return null; 1194 } 1195 1196 pgroup = (Group) groupList.get(parentChoice.getSelectedIndex()); 1197 if (pgroup == null) { 1198 toolkit.beep(); 1199 JOptionPane.showMessageDialog(this, "Parent group is null.", getTitle(), JOptionPane.ERROR_MESSAGE); 1200 return null; 1201 } 1202 1203 TableView tableView = (TableView) dataView; 1204 Object theData = tableView.getSelectedData(); 1205 if (theData == null) { 1206 return null; 1207 } 1208 1209 int w = tableView.getTable().getSelectedColumnCount(); 1210 int h = tableView.getTable().getSelectedRowCount(); 1211 Dataset dataset = (Dataset) tableView.getDataObject(); 1212 if (dataset instanceof ScalarDS) { 1213 ScalarDS sd = (ScalarDS) dataset; 1214 if (sd.isUnsigned()) { 1215 theData = Dataset.convertToUnsignedC(theData, null); 1216 } 1217 } 1218 1219 try { 1220 long[] dims = { h, w }; 1221 obj = dataset.copy(pgroup, name, dims, theData); 1222 } 1223 catch (Exception ex) { 1224 toolkit.beep(); 1225 JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE); 1226 return null; 1227 } 1228 1229 return obj; 1230 } 1231 1232 private HObject createFromImage() { 1233 HObject obj = null; 1234 String name = null; 1235 Group pgroup = null; 1236 1237 name = nameField.getText(); 1238 if (name == null) { 1239 toolkit.beep(); 1240 JOptionPane 1241 .showMessageDialog(this, "Dataset name is not specified.", getTitle(), JOptionPane.ERROR_MESSAGE); 1242 return null; 1243 } 1244 1245 if (name.indexOf(HObject.separator) >= 0) { 1246 toolkit.beep(); 1247 JOptionPane.showMessageDialog(this, "Dataset name cannot contain path.", getTitle(), 1248 JOptionPane.ERROR_MESSAGE); 1249 return null; 1250 } 1251 1252 pgroup = (Group) groupList.get(parentChoice.getSelectedIndex()); 1253 if (pgroup == null) { 1254 toolkit.beep(); 1255 JOptionPane.showMessageDialog(this, "Parent group is null.", getTitle(), JOptionPane.ERROR_MESSAGE); 1256 return null; 1257 } 1258 1259 ImageView imageView = (ImageView) dataView; 1260 ScalarDS dataset = (ScalarDS) imageView.getDataObject(); 1261 Object theData = imageView.getSelectedData(); 1262 1263 if (theData == null) { 1264 return null; 1265 } 1266 1267 // in version 2.4, unsigned image data is converted to signed data 1268 // to write data, the data needs to converted back to unsigned. 1269 if (dataset.isUnsigned()) { 1270 theData = Dataset.convertToUnsignedC(theData, null); 1271 } 1272 1273 int w = imageView.getSelectedArea().width; 1274 int h = imageView.getSelectedArea().height; 1275 1276 try { 1277 long[] dims = null; 1278 if (isH5) { 1279 if (imageView.isTrueColor()) { 1280 dims = new long[3]; 1281 if (imageView.isPlaneInterlace()) { 1282 dims[0] = 3; 1283 dims[1] = h; 1284 dims[2] = w; 1285 } 1286 else { 1287 dims[0] = h; 1288 dims[1] = w; 1289 dims[2] = 3; 1290 } 1291 } 1292 else { 1293 dims = new long[2]; 1294 dims[0] = h; 1295 dims[1] = w; 1296 } 1297 } 1298 else { 1299 dims = new long[2]; 1300 dims[0] = w; 1301 dims[1] = h; 1302 } 1303 1304 obj = dataset.copy(pgroup, name, dims, theData); 1305 } 1306 catch (Exception ex) { 1307 toolkit.beep(); 1308 JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE); 1309 return null; 1310 } 1311 1312 return obj; 1313 } 1314 1315 /** Returns the new dataset created. */ 1316 public DataFormat getObject() { 1317 return newObject; 1318 } 1319 1320 /** Returns the parent group of the new dataset. */ 1321 public Group getParentGroup() { 1322 return (Group) groupList.get(parentChoice.getSelectedIndex()); 1323 } 1324 1325}