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 file COPYING. * 009 * COPYING can be found at the root of the source code distribution tree. * 010 * If you do not have access to this file, you may request a copy from * 011 * help@hdfgroup.org. * 012 ****************************************************************************/ 013 014package hdf.view; 015 016import java.awt.BorderLayout; 017import java.awt.Dimension; 018import java.awt.GridLayout; 019import java.awt.Insets; 020import java.awt.Point; 021import java.awt.event.ActionEvent; 022import java.awt.event.ActionListener; 023import java.awt.event.KeyEvent; 024import java.io.File; 025import java.lang.reflect.Array; 026import java.math.BigInteger; 027import java.util.Enumeration; 028import java.util.List; 029import java.util.StringTokenizer; 030 031import javax.swing.BorderFactory; 032import javax.swing.CellEditor; 033import javax.swing.JButton; 034import javax.swing.JComboBox; 035import javax.swing.JDialog; 036import javax.swing.JFileChooser; 037import javax.swing.JFrame; 038import javax.swing.JInternalFrame; 039import javax.swing.JLabel; 040import javax.swing.JOptionPane; 041import javax.swing.JPanel; 042import javax.swing.JScrollPane; 043import javax.swing.JSplitPane; 044import javax.swing.JTabbedPane; 045import javax.swing.JTable; 046import javax.swing.JTextArea; 047import javax.swing.JTextField; 048import javax.swing.ListSelectionModel; 049import javax.swing.border.TitledBorder; 050import javax.swing.event.ChangeEvent; 051import javax.swing.table.DefaultTableModel; 052import javax.swing.tree.DefaultMutableTreeNode; 053 054import hdf.object.Attribute; 055import hdf.object.CompoundDS; 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 * DefaultMetadataView is an dialog window used to show data properties. Data 065 * properties include attributes and general information such as object type, 066 * data type and data space. 067 * 068 * @author Peter X. Cao 069 * @version 2.4 9/6/2007 070 */ 071public class DefaultMetaDataView extends JDialog implements ActionListener, MetaDataView { 072 private static final long serialVersionUID = 7891048909810508761L; 073 074 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DefaultMetaDataView.class); 075 076 /** 077 * The main HDFView. 078 */ 079 private ViewManager viewer; 080 081 /** The HDF data object */ 082 private HObject hObject; 083 084 private JTabbedPane tabbedPane = null; 085 private JTextArea attrContentArea; 086 private JTable attrTable; // table to hold a list of attributes 087 private DefaultTableModel attrTableModel; 088 private JLabel attrNumberLabel; 089 private int numAttributes; 090 private boolean isH5, isH4; 091 private byte[] userBlock; 092 private JTextArea userBlockArea; 093 private JButton jamButton; 094 095 private JTextField linkField = null; 096 097 private FileFormat fileFormat; 098 private String LinkTObjName; 099 100 private int[] libver; 101 102 /** 103 * Constructs a DefaultMetadataView with the given HDFView. 104 * 105 * @param theView The main HDFView 106 */ 107 public DefaultMetaDataView(ViewManager theView) { 108 super((JFrame) theView, false); 109 setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE); 110 111 setName("DefaultMetaDataView"); 112 viewer = theView; 113 hObject = viewer.getTreeView().getCurrentObject(); 114 fileFormat = hObject.getFileFormat(); 115 numAttributes = 0; 116 userBlock = null; 117 userBlockArea = null; 118 libver = new int[2]; 119 120 if (hObject == null) { 121 dispose(); 122 } 123 else if (hObject.getPath() == null) { 124 setTitle("Properties - " + hObject.getName()); 125 } 126 else { 127 setTitle("Properties - " + hObject.getPath() + hObject.getName()); 128 } 129 130 isH5 = hObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5)); 131 isH4 = hObject.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4)); 132 133 tabbedPane = new JTabbedPane(); 134 // get the metadata information before add GUI components */ 135 try { 136 log.trace("DefaultMetaDataView: start"); 137 hObject.getMetadata(); 138 } 139 catch (Exception ex) { 140 log.debug("get the metadata information before add GUI components:", ex); 141 } 142 tabbedPane.addTab("General", createGeneralPropertyPanel()); 143 tabbedPane.addTab("Attributes", createAttributePanel()); 144 145 boolean isRoot = ((hObject instanceof Group) && ((Group) hObject).isRoot()); 146 if (isH5 && isRoot) { 147 // add panel to display user block 148 tabbedPane.addTab("User Block", createUserBlockPanel()); 149 } 150 tabbedPane.setSelectedIndex(0); 151 152 if (isH5) { 153 if (hObject.getLinkTargetObjName() != null) { 154 LinkTObjName = hObject.getLinkTargetObjName(); 155 } 156 } 157 JPanel bPanel = new JPanel(); 158 bPanel.setName("MetaDataClose"); 159 JButton b = new JButton(" Close "); 160 b.setName("Close"); 161 b.setMnemonic(KeyEvent.VK_C); 162 b.setActionCommand("Close"); 163 b.addActionListener(this); 164 bPanel.add(b); 165 166 // Add the tabbed pane to this panel. 167 JPanel contentPane = (JPanel) getContentPane(); 168 contentPane.setName("MetaDataContent"); 169 contentPane.setLayout(new BorderLayout()); 170 contentPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 171 contentPane.setPreferredSize(new Dimension(620, 400)); 172 173 contentPane.add("Center", tabbedPane); 174 contentPane.add("South", bPanel); 175 176 // locate the H5Property dialog 177 Point l = getParent().getLocation(); 178 l.x += 250; 179 l.y += 80; 180 setLocation(l); 181 pack(); 182 setVisible(true); 183 } 184 185 @SuppressWarnings("rawtypes") 186 public void actionPerformed(ActionEvent e) { 187 Object source = e.getSource(); 188 String cmd = e.getActionCommand(); 189 190 if (cmd.equals("Close")) { 191 if (isH5 && linkField != null) checkLinkTargetChanged(); 192 193 dispose(); 194 } 195 else if (cmd.equals("Add attribute")) { 196 addAttribute(hObject); 197 } 198 else if (cmd.equals("Delete attribute")) { 199 deleteAttribute(hObject); 200 } 201 else if (cmd.equals("Jam user block")) { 202 writeUserBlock(); 203 } 204 else if (cmd.equals("Display user block as")) { 205 int type = 0; 206 String typeName = (String) ((JComboBox) source).getSelectedItem(); 207 jamButton.setEnabled(false); 208 userBlockArea.setEditable(false); 209 210 if (typeName.equalsIgnoreCase("Text")) { 211 type = 0; 212 jamButton.setEnabled(true); 213 userBlockArea.setEditable(true); 214 } 215 else if (typeName.equalsIgnoreCase("Binary")) { 216 type = 2; 217 } 218 else if (typeName.equalsIgnoreCase("Octal")) { 219 type = 8; 220 } 221 else if (typeName.equalsIgnoreCase("Hexadecimal")) { 222 type = 16; 223 } 224 else if (typeName.equalsIgnoreCase("Decimal")) { 225 type = 10; 226 } 227 228 showUserBlockAs(type); 229 } 230 } 231 232 private final void checkLinkTargetChanged() { 233 Group pgroup = null; 234 try { 235 pgroup = (Group) hObject.getFileFormat().get(hObject.getPath()); 236 } 237 catch (Exception ex) { 238 log.debug("parent group:", ex); 239 } 240 if (pgroup == null) { 241 JOptionPane.showMessageDialog(this, "Parent group is null.", getTitle(), JOptionPane.ERROR_MESSAGE); 242 return; 243 } 244 245 String target_name = linkField.getText(); 246 if (target_name != null) target_name = target_name.trim(); 247 248 int linkType = Group.LINK_TYPE_SOFT; 249 if (LinkTObjName.contains(FileFormat.FILE_OBJ_SEP)) 250 linkType = Group.LINK_TYPE_EXTERNAL; 251 else if (target_name.equals("/")) // do not allow to link to the root 252 return; 253 254 // no change 255 if (target_name.equals(hObject.getLinkTargetObjName())) return; 256 257 // invalid name 258 if (target_name == null || target_name.length() < 1) return; 259 260 try { 261 fileFormat.createLink(pgroup, hObject.getName(), target_name, linkType); 262 hObject.setLinkTargetObjName(target_name); 263 } 264 catch (Exception ex) { 265 JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE); 266 } 267 } 268 269 /** returns the data object displayed in this data viewer */ 270 public HObject getDataObject() { 271 return hObject; 272 } 273 274 /** Disposes of this dataobserver. */ 275 public void dispose() { 276 super.dispose(); 277 } 278 279 /** add an attribute to a data object. */ 280 public Attribute addAttribute(HObject obj) { 281 if (obj == null) { 282 return null; 283 } 284 285 DefaultMutableTreeNode node = (DefaultMutableTreeNode) obj.getFileFormat().getRootNode(); 286 NewAttributeDialog dialog = new NewAttributeDialog(this, obj, node.breadthFirstEnumeration()); 287 dialog.setVisible(true); 288 289 Attribute attr = dialog.getAttribute(); 290 if (attr == null) { 291 return null; 292 } 293 294 String rowData[] = new String[4]; // name, value, type, size 295 296 rowData[0] = attr.getName(); 297 rowData[2] = attr.getType().getDatatypeDescription(); 298 299 rowData[1] = attr.toString(", "); 300 301 long dims[] = attr.getDataDims(); 302 303 rowData[3] = String.valueOf(dims[0]); 304 for (int j = 1; j < dims.length; j++) { 305 rowData[3] += " x " + dims[j]; 306 } 307 308 attrTableModel.addRow(rowData); 309 attrTableModel.fireTableRowsInserted(attrTableModel.getRowCount() - 1, attrTableModel.getRowCount() - 1); 310 numAttributes++; 311 attrContentArea.setText(""); 312 attrNumberLabel.setText("Number of attributes = " + numAttributes); 313 314 return attr; 315 } 316 317 /** delete an attribute from a data object. */ 318 public Attribute deleteAttribute(HObject obj) { 319 if (obj == null) { 320 return null; 321 } 322 323 int idx = attrTable.getSelectedRow(); 324 if (idx < 0) { 325 JOptionPane.showMessageDialog(getOwner(), "No attribute is selected.", getTitle(), 326 JOptionPane.ERROR_MESSAGE); 327 return null; 328 } 329 330 int option = JOptionPane.showConfirmDialog(this, "Do you want to delete the selected attribute?", getTitle(), 331 JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); 332 333 if (option == JOptionPane.NO_OPTION) { 334 return null; 335 } 336 337 List<?> attrList = null; 338 try { 339 attrList = obj.getMetadata(); 340 } 341 catch (Exception ex) { 342 attrList = null; 343 } 344 345 if (attrList == null) { 346 return null; 347 } 348 349 Attribute attr = (Attribute) attrList.get(idx); 350 try { 351 obj.removeMetadata(attr); 352 } 353 catch (Exception ex) { 354 log.debug("delete an attribute from a data object:", ex); 355 } 356 357 attrTableModel.removeRow(idx); 358 numAttributes--; 359 attrTableModel.fireTableRowsDeleted(idx, idx); 360 361 attrContentArea.setText(""); 362 attrNumberLabel.setText("Number of attributes = " + numAttributes); 363 364 return attr; 365 } 366 367 /** 368 * Creates a panel used to display general information of HDF object. 369 */ 370 private JPanel createGeneralPropertyPanel() { 371 JPanel panel = new JPanel(); 372 panel.setLayout(new BorderLayout(10, 10)); 373 panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); 374 boolean isRoot = ((hObject instanceof Group) && ((Group) hObject).isRoot()); 375 FileFormat theFile = hObject.getFileFormat(); 376 377 JPanel topPanel = new JPanel(); 378 topPanel.setLayout(new BorderLayout()); 379 380 JPanel lp = new JPanel(); 381 lp.setLayout(new GridLayout(5, 1)); 382 383 if (isRoot) { 384 lp.add(new JLabel("File Name: ")); 385 lp.add(new JLabel("File Path: ")); 386 lp.add(new JLabel("File Type: ")); 387 if (isH5) { 388 try { 389 libver = hObject.getFileFormat().getLibBounds(); 390 } 391 catch (Exception ex) { 392 ex.printStackTrace(); 393 } 394 if (((libver[0] == 0) || (libver[0] == 1)) && (libver[1] == 1)) 395 lp.add(new JLabel("Library version: ")); 396 } 397 } 398 else { 399 lp.add(new JLabel("Name: ")); 400 if (isH5) { 401 if (hObject.getLinkTargetObjName() != null) lp.add(new JLabel("Link To Target: ")); 402 } 403 lp.add(new JLabel("Path: ")); 404 lp.add(new JLabel("Type: ")); 405 406 /* bug #926 to remove the OID, put it back on Nov. 20, 2008, --PC */ 407 if (isH4) { 408 lp.add(new JLabel("Tag, Ref: ")); 409 } 410 else { 411 lp.add(new JLabel("Object Ref: ")); 412 } 413 } 414 415 JPanel rp = new JPanel(); 416 rp.setLayout(new GridLayout(5, 1)); 417 418 JLabel nameField = new JLabel(hObject.getName()); 419 nameField.setName("namefield"); 420 rp.add(nameField); 421 422 JPanel targetObjPanel = new JPanel(); 423 JButton ChangeTargetObjButton = new JButton("Change"); 424 ChangeTargetObjButton.setActionCommand("Change link target"); 425 ChangeTargetObjButton.addActionListener(this); 426 427 if (isH5) { 428 if (hObject.getLinkTargetObjName() != null) { 429 linkField = new JTextField(hObject.getLinkTargetObjName()); 430 linkField.setName("linkField"); 431 targetObjPanel.setLayout(new BorderLayout()); 432 targetObjPanel.add(linkField, BorderLayout.CENTER); 433 // targetObjPanel.add(ChangeTargetObjButton, BorderLayout.EAST); 434 rp.add(targetObjPanel); 435 } 436 } 437 438 JLabel pathField = new JLabel(); 439 if (isRoot) { 440 pathField.setText((new File(hObject.getFile())).getParent()); 441 } 442 else { 443 pathField.setText(hObject.getPath()); 444 } 445 rp.add(pathField); 446 447 String typeStr = "Unknown"; 448 String fileInfo = ""; 449 if (isRoot) { 450 long size = 0; 451 try { 452 size = (new File(hObject.getFile())).length(); 453 } 454 catch (Exception ex) { 455 size = -1; 456 } 457 size /= 1024; 458 459 int groupCount = 0, datasetCount = 0; 460 DefaultMutableTreeNode root = (DefaultMutableTreeNode) theFile.getRootNode(); 461 DefaultMutableTreeNode theNode = null; 462 Enumeration<?> local_enum = root.depthFirstEnumeration(); 463 while (local_enum.hasMoreElements()) { 464 theNode = (DefaultMutableTreeNode) local_enum.nextElement(); 465 if (theNode.getUserObject() instanceof Group) { 466 groupCount++; 467 } 468 else { 469 datasetCount++; 470 } 471 } 472 fileInfo = "size=" + size + "K, groups=" + groupCount + ", datasets=" + datasetCount; 473 } 474 475 if (isRoot) { 476 if (isH5) { 477 typeStr = "HDF5, " + fileInfo; 478 } 479 else if (isH4) { 480 typeStr = "HDF4, " + fileInfo; 481 } 482 else { 483 typeStr = fileInfo; 484 } 485 } 486 else if (isH5) { 487 if (hObject instanceof Group) { 488 typeStr = "HDF5 Group"; 489 } 490 else if (hObject instanceof ScalarDS) { 491 typeStr = "HDF5 Scalar Dataset"; 492 } 493 else if (hObject instanceof CompoundDS) { 494 typeStr = "HDF5 Compound Dataset"; 495 } 496 else if (hObject instanceof Datatype) { 497 typeStr = "HDF5 Named Datatype"; 498 } 499 } 500 else if (isH4) { 501 if (hObject instanceof Group) { 502 typeStr = "HDF4 Group"; 503 } 504 else if (hObject instanceof ScalarDS) { 505 ScalarDS ds = (ScalarDS) hObject; 506 if (ds.isImage()) { 507 typeStr = "HDF4 Raster Image"; 508 } 509 else { 510 typeStr = "HDF4 SDS"; 511 } 512 } 513 else if (hObject instanceof CompoundDS) { 514 typeStr = "HDF4 Vdata"; 515 } 516 } 517 else { 518 if (hObject instanceof Group) { 519 typeStr = "Group"; 520 } 521 else if (hObject instanceof ScalarDS) { 522 typeStr = "Scalar Dataset"; 523 } 524 else if (hObject instanceof CompoundDS) { 525 typeStr = "Compound Dataset"; 526 } 527 } 528 529 JLabel typeField = new JLabel(typeStr); 530 rp.add(typeField); 531 532 if (isRoot && isH5) { 533 String libversion = null; 534 if ((libver[0] == 0) && (libver[1] == 1)) 535 libversion = "Earliest and Latest"; 536 else if ((libver[0] == 1) && (libver[1] == 1)) libversion = "Latest and Latest"; 537 JLabel libverbound = new JLabel(libversion); 538 libverbound.setName("libverbound"); 539 rp.add(libverbound); 540 } 541 542 /* bug #926 to remove the OID, put it back on Nov. 20, 2008, --PC */ 543 String oidStr = null; 544 long[] OID = hObject.getOID(); 545 if (OID != null) { 546 oidStr = String.valueOf(OID[0]); 547 for (int i = 1; i < OID.length; i++) { 548 oidStr += ", " + OID[i]; 549 } 550 } 551 552 if (!isRoot) { 553 JLabel oidField = new JLabel(oidStr); 554 rp.add(oidField); 555 } 556 557 JPanel tmpP = new JPanel(); 558 tmpP.setLayout(new BorderLayout()); 559 tmpP.add("West", lp); 560 tmpP.add("Center", rp); 561 tmpP.setBorder(new TitledBorder("")); 562 563 topPanel.add("North", new JLabel("")); 564 topPanel.add("Center", tmpP); 565 566 JPanel infoPanel = null; 567 if (hObject instanceof Group) { 568 infoPanel = createGroupInfoPanel((Group) hObject); 569 } 570 else if (hObject instanceof Dataset) { 571 infoPanel = createDatasetInfoPanel((Dataset) hObject); 572 } 573 else if (hObject instanceof Datatype) { 574 infoPanel = createNamedDatatypeInfoPanel((Datatype) hObject); 575 } 576 577 panel.add(topPanel, BorderLayout.NORTH); 578 if (infoPanel != null) { 579 panel.add(infoPanel, BorderLayout.CENTER); 580 } 581 582 return panel; 583 } 584 585 /** 586 * Creates a panel used to display HDF group information. 587 */ 588 private JPanel createGroupInfoPanel(Group g) { 589 JPanel panel = new JPanel(); 590 591 List<?> mlist = g.getMemberList(); 592 if (mlist == null) { 593 return panel; 594 } 595 596 int n = mlist.size(); 597 if (n <= 0) { 598 return panel; 599 } 600 601 String rowData[][] = new String[n][2]; 602 for (int i = 0; i < n; i++) { 603 HObject theObj = (HObject) mlist.get(i); 604 rowData[i][0] = theObj.getName(); 605 if (theObj instanceof Group) { 606 rowData[i][1] = "Group"; 607 } 608 else if (theObj instanceof Dataset) { 609 rowData[i][1] = "Dataset"; 610 } 611 } 612 613 String[] columnNames = { "Name", "Type" }; 614 JTable table = new JTable(rowData, columnNames) { 615 private static final long serialVersionUID = -834321929059590629L; 616 617 public boolean isCellEditable(int row, int column) { 618 return false; 619 } 620 }; 621 table.setName("GroupInfo"); 622 table.setCellSelectionEnabled(false); 623 624 // set cell height for large fonts 625 int cellRowHeight = Math.max(16, table.getFontMetrics(table.getFont()).getHeight()); 626 table.setRowHeight(cellRowHeight); 627 628 table.getTableHeader().setReorderingAllowed(false); 629 JScrollPane scroller = new JScrollPane(table); 630 631 panel.setLayout(new BorderLayout()); 632 if (g.getNumberOfMembersInFile() < ViewProperties.getMaxMembers()) { 633 panel.add(new JLabel("Number of members: " + n), BorderLayout.NORTH); 634 } 635 else { 636 panel.add(new JLabel("Number of members: " + n + " (in memory), " + g.getNumberOfMembersInFile() 637 + " (in file)"), BorderLayout.NORTH); 638 } 639 panel.add(scroller, BorderLayout.CENTER); 640 panel.setBorder(new TitledBorder("Group Members")); 641 642 return panel; 643 } 644 645 private JPanel createNamedDatatypeInfoPanel(Datatype t) { 646 JPanel panel = new JPanel(); 647 panel.setLayout(new BorderLayout()); 648 JTextArea infoArea = new JTextArea(t.getDatatypeDescription()); 649 infoArea.setEditable(false); 650 651 panel.add(infoArea, BorderLayout.CENTER); 652 653 return panel; 654 } 655 656 /** 657 * Creates a panel used to display HDF dataset information. 658 */ 659 private JPanel createDatasetInfoPanel(Dataset d) { 660 JPanel lp = new JPanel(); 661 lp.setLayout(new GridLayout(4, 1)); 662 lp.add(new JLabel("No. of Dimension(s): ")); 663 lp.add(new JLabel("Dimension Size(s): ")); 664 lp.add(new JLabel("Max Dimension Size(s): ")); 665 lp.add(new JLabel("Data Type: ")); 666 667 JPanel rp = new JPanel(); 668 rp.setLayout(new GridLayout(4, 1)); 669 log.trace("createDatasetInfoPanel: start"); 670 671 JTextField txtf = new JTextField("" + d.getRank()); 672 txtf.setName("dimensions"); 673 txtf.setEditable(false); 674 rp.add(txtf); 675 log.trace("createDatasetInfoPanel inited"); 676 677 String dimStr = null; 678 String maxDimStr = null; 679 long dims[] = d.getDims(); 680 long maxDims[] = d.getMaxDims(); 681 if (dims != null) { 682 String[] dimNames = d.getDimNames(); 683 boolean hasDimNames = ((dimNames != null) && (dimNames.length == dims.length)); 684 StringBuffer sb = new StringBuffer(); 685 StringBuffer sb2 = new StringBuffer(); 686 687 sb.append(dims[0]); 688 if (hasDimNames) { 689 sb.append(" ("); 690 sb.append(dimNames[0]); 691 sb.append(")"); 692 } 693 694 if (maxDims[0] < 0) 695 sb2.append("Unlimited"); 696 else 697 sb2.append(maxDims[0]); 698 699 for (int i = 1; i < dims.length; i++) { 700 sb.append(" x "); 701 sb.append(dims[i]); 702 if (hasDimNames) { 703 sb.append(" ("); 704 sb.append(dimNames[i]); 705 sb.append(")"); 706 } 707 708 sb2.append(" x "); 709 if (maxDims[i] < 0) 710 sb2.append("Unlimited"); 711 else 712 sb2.append(maxDims[i]); 713 714 } 715 dimStr = sb.toString(); 716 maxDimStr = sb2.toString(); 717 } 718 txtf = new JTextField(dimStr); 719 txtf.setName("dimensionsize"); 720 txtf.setEditable(false); 721 rp.add(txtf); 722 723 txtf = new JTextField(maxDimStr); 724 txtf.setEditable(false); 725 rp.add(txtf); 726 727 String typeStr = null; 728 if (d instanceof ScalarDS) { 729 ScalarDS sd = (ScalarDS) d; 730 typeStr = sd.getDatatype().getDatatypeDescription(); 731 } 732 else if (d instanceof CompoundDS) { 733 if (isH4) { 734 typeStr = "Vdata"; 735 } 736 else { 737 typeStr = "Compound"; 738 } 739 } 740 741 txtf = new JTextField(typeStr); 742 txtf.setEditable(false); 743 rp.add(txtf); 744 745 JPanel infoP = new JPanel(); 746 infoP.setLayout(new BorderLayout()); 747 infoP.add(lp, BorderLayout.WEST); 748 infoP.add(rp, BorderLayout.CENTER); 749 infoP.setBorder(new TitledBorder("")); 750 751 JPanel panel = new JPanel(); 752 panel.setLayout(new BorderLayout()); 753 panel.add(infoP, BorderLayout.NORTH); 754 panel.setBorder(new TitledBorder("Dataspace and Datatype")); 755 756 // add compound datatype information 757 if (d instanceof CompoundDS) { 758 CompoundDS compound = (CompoundDS) d; 759 760 int n = compound.getMemberCount(); 761 if (n > 0) { 762 String rowData[][] = new String[n][3]; 763 String names[] = compound.getMemberNames(); 764 Datatype types[] = compound.getMemberTypes(); 765 int orders[] = compound.getMemberOrders(); 766 767 for (int i = 0; i < n; i++) { 768 rowData[i][0] = names[i]; 769 int mDims[] = compound.getMemberDims(i); 770 if (mDims == null) { 771 rowData[i][2] = String.valueOf(orders[i]); 772 773 if (isH4 && types[i].getDatatypeClass() == Datatype.CLASS_STRING) { 774 rowData[i][2] = String.valueOf(types[i].getDatatypeSize()); 775 } 776 } 777 else { 778 String mStr = String.valueOf(mDims[0]); 779 int m = mDims.length; 780 for (int j = 1; j < m; j++) { 781 mStr += " x " + mDims[j]; 782 } 783 rowData[i][2] = mStr; 784 } 785 rowData[i][1] = types[i].getDatatypeDescription(); 786 } 787 788 String[] columnNames = { "Name", "Type", "Array Size" }; 789 JTable table = new JTable(rowData, columnNames) { 790 private static final long serialVersionUID = -1517773307922536859L; 791 792 public boolean isCellEditable(int row, int column) { 793 return false; 794 } 795 }; 796 table.setName("CompoundMetaData"); 797 table.setCellSelectionEnabled(false); 798 table.getTableHeader().setReorderingAllowed(false); 799 panel.add(new JScrollPane(table), BorderLayout.CENTER); 800 801 // set cell height for large fonts 802 int cellRowHeight = Math.max(16, table.getFontMetrics(table.getFont()).getHeight()); 803 table.setRowHeight(cellRowHeight); 804 } // if (n > 0) 805 } // if (d instanceof Compound) 806 807 // // add compression and data layout information 808 // try { d.getMetadata(); } catch (Exception ex) {} 809 String chunkInfo = ""; 810 long[] chunks = d.getChunkSize(); 811 if (chunks == null) { 812 chunkInfo = "NONE"; 813 } 814 else { 815 int n = chunks.length; 816 chunkInfo = String.valueOf(chunks[0]); 817 for (int i = 1; i < n; i++) { 818 chunkInfo += " X " + chunks[i]; 819 } 820 } 821 822 JPanel bPanel = new JPanel(); 823 bPanel.setBorder(new TitledBorder("")); 824 bPanel.setLayout(new BorderLayout()); 825 lp = new JPanel(); 826 lp.setName("genmetainfo"); 827 lp.setLayout(new GridLayout(5, 1)); 828 lp.add(new JLabel("Chunking: ")); 829 lp.add(new JLabel("Compression: ")); 830 lp.add(new JLabel("Filters: ")); 831 lp.add(new JLabel("Storage: ")); 832 lp.add(new JLabel("Fill value: ")); 833 bPanel.add(lp, BorderLayout.WEST); 834 835 Object fillValue = null; 836 String fillValueInfo = "NONE"; 837 if (d instanceof ScalarDS) fillValue = ((ScalarDS) d).getFillValue(); 838 if (fillValue != null) { 839 if (fillValue.getClass().isArray()) { 840 int len = Array.getLength(fillValue); 841 fillValueInfo = Array.get(fillValue, 0).toString(); 842 for (int i = 1; i < len; i++) { 843 fillValueInfo += ", "; 844 fillValueInfo += Array.get(fillValue, i).toString(); 845 } 846 } 847 else 848 fillValueInfo = fillValue.toString(); 849 } 850 851 rp = new JPanel(); 852 rp.setName("genmetadata"); 853 rp.setLayout(new GridLayout(5, 1)); 854 JLabel rpchunk = new JLabel(chunkInfo); 855 rpchunk.setName("chunkdata"); 856 rp.add(rpchunk); 857 JLabel rpcomp = new JLabel(d.getCompression()); 858 rpcomp.setName("compressiondata"); 859 rp.add(rpcomp); 860 JLabel rpfilt = new JLabel(d.getFilters()); 861 rpfilt.setName("filterdata"); 862 rp.add(rpfilt); 863 JLabel rpstore = new JLabel(d.getStorage()); 864 rpstore.setName("storagedata"); 865 rp.add(rpstore); 866 JLabel rpfillval = new JLabel(fillValueInfo); 867 rpfillval.setName("fillvaluedata"); 868 rp.add(rpfillval); 869 bPanel.add(rp, BorderLayout.CENTER); 870 871 panel.add(bPanel, BorderLayout.SOUTH); 872 log.trace("createDatasetInfoPanel: finish"); 873 874 return panel; 875 } 876 877 /** 878 * Creates a panel used to display attribute information. 879 */ 880 private JPanel createAttributePanel() { 881 JPanel panel = new JPanel(); 882 panel.setLayout(new BorderLayout()); 883 // panel.setBorder(BorderFactory.createEmptyBorder(10,0,0,0)); 884 885 JPanel topPanel = new JPanel(); 886 topPanel.setLayout(new BorderLayout()); 887 attrNumberLabel = new JLabel("Number of attributes = 0"); 888 topPanel.add(attrNumberLabel, BorderLayout.WEST); 889 890 FileFormat theFile = hObject.getFileFormat(); 891 JPanel bPanel = new JPanel(); 892 JButton b = new JButton(" Add "); 893 b.setName("Add"); 894 b.setMnemonic('A'); 895 b.addActionListener(this); 896 b.setActionCommand("Add attribute"); 897 bPanel.add(b); 898 b.setEnabled(!theFile.isReadOnly()); 899 900 if (isH5) { 901 // deleting is not supported by HDF4 902 b = new JButton("Delete"); 903 b.setName("Delete"); 904 b.setMnemonic('D'); 905 b.addActionListener(this); 906 b.setActionCommand("Delete attribute"); 907 bPanel.add(b); 908 b.setEnabled(!theFile.isReadOnly()); 909 } 910 topPanel.add(bPanel, BorderLayout.EAST); 911 912 panel.add(topPanel, BorderLayout.NORTH); 913 914 List<?> attrList = null; 915 log.trace("createAttributePanel: start"); 916 917 try { 918 attrList = hObject.getMetadata(); 919 } 920 catch (Exception ex) { 921 attrList = null; 922 } 923 if (attrList != null) { 924 numAttributes = attrList.size(); 925 } 926 log.trace("createAttributePanel: isH5={} numAttributes={}", isH5, numAttributes); 927 928 String[] columnNames = { "Name", "Value", "Type", "Array Size" }; 929 attrTableModel = new DefaultTableModel(columnNames, numAttributes); 930 931 attrTable = new JTable(attrTableModel) { 932 private static final long serialVersionUID = 2590244645972259454L; 933 int lastSelectedRow = -1; 934 int lastSelectedCol = -1; 935 936 public boolean isCellEditable(int row, int column) { 937 return ((column == 1) || (isH5 && (column == 0))); 938 // only attribute value and name can be changed 939 } 940 941 public void editingStopped(ChangeEvent e) { 942 int row = getEditingRow(); 943 int col = getEditingColumn(); 944 String oldValue = (String) getValueAt(row, col); 945 946 super.editingStopped(e); 947 948 Object source = e.getSource(); 949 950 if (source instanceof CellEditor) { 951 CellEditor editor = (CellEditor) source; 952 String newValue = (String) editor.getCellEditorValue(); 953 setValueAt(oldValue, row, col); // set back to what it is 954 updateAttributeValue(newValue, row, col); 955 } 956 } 957 958 public boolean isCellSelected(int row, int col) { 959 960 if ((getSelectedRow() == row) && (getSelectedColumn() == col) 961 && !((lastSelectedRow == row) && (lastSelectedCol == col))) { 962 // selection is changed 963 Object attrV = getValueAt(row, col); 964 if (attrV != null) { 965 attrContentArea.setText(attrV.toString()); 966 } 967 lastSelectedRow = row; 968 lastSelectedCol = col; 969 } 970 971 return super.isCellSelected(row, col); 972 } 973 }; 974 975 attrTable.setName("attributes"); 976 attrTable.setRowSelectionAllowed(false); 977 attrTable.setCellSelectionEnabled(true); 978 attrTable.getTableHeader().setReorderingAllowed(false); 979 attrTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 980 981 // set cell height for large fonts 982 int cellRowHeight = Math.max(16, attrTable.getFontMetrics(attrTable.getFont()).getHeight()); 983 attrTable.setRowHeight(cellRowHeight); 984 985 JScrollPane scroller1 = new JScrollPane(attrTable); 986 attrContentArea = new JTextArea(); 987 attrContentArea.setLineWrap(true); 988 attrContentArea.setEditable(false); 989 Insets m = new Insets(5, 5, 5, 5); 990 attrContentArea.setMargin(m); 991 992 JScrollPane scroller2 = new JScrollPane(attrContentArea); 993 JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scroller1, scroller2); 994 995 // set the divider location 996 int h = Math.min((numAttributes + 2) * attrTable.getRowHeight(), scroller1.getPreferredSize().height - 40); 997 splitPane.setDividerLocation(h); 998 panel.add(splitPane, BorderLayout.CENTER); 999 1000 if (attrList == null) { 1001 log.trace("createAttributePanel: attrList == null"); 1002 return panel; 1003 } 1004 1005 Attribute attr = null; 1006 String name, type, size; 1007 attrNumberLabel.setText("Number of attributes = " + numAttributes); 1008 for (int i = 0; i < numAttributes; i++) { 1009 attr = (Attribute) attrList.get(i); 1010 name = attr.getName(); 1011 type = attr.getType().getDatatypeDescription(); 1012 log.trace("createAttributePanel: attr[{}] is {} as {}", i, name, type); 1013 1014 if (attr.isScalar()) { 1015 size = "Scalar"; 1016 } 1017 else { 1018 long dims[] = attr.getDataDims(); 1019 size = String.valueOf(dims[0]); 1020 for (int j = 1; j < dims.length; j++) { 1021 size += " x " + dims[j]; 1022 } 1023 } 1024 1025 if (attr.getProperty("field") !=null) { 1026 String fieldInfo = " {Field: "+attr.getProperty("field")+"}"; 1027 attrTable.setValueAt(name+fieldInfo, i, 0); 1028 } 1029 else 1030 attrTable.setValueAt(name, i, 0); 1031 1032 attrTable.setValueAt(attr.toString(", "), i, 1); 1033 attrTable.setValueAt(type, i, 2); 1034 attrTable.setValueAt(size, i, 3); 1035 } // for (int i=0; i<n; i++) 1036 1037 log.trace("createAttributePanel: finish"); 1038 return panel; 1039 } 1040 1041 /** 1042 * Creates a panel used to display HDF5 user block. 1043 */ 1044 @SuppressWarnings({ "rawtypes", "unchecked" }) 1045 private JPanel createUserBlockPanel() { 1046 JPanel panel = new JPanel(); 1047 1048 userBlock = DefaultFileFilter.getHDF5UserBlock(hObject.getFile()); 1049 1050 panel.setLayout(new BorderLayout(10, 10)); 1051 panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); 1052 userBlockArea = new JTextArea(); 1053 userBlockArea.setEditable(true); 1054 userBlockArea.setLineWrap(true); 1055 Insets m = new Insets(5, 5, 5, 5); 1056 userBlockArea.setMargin(m); 1057 1058 String[] displayChoices = { "Text", "Binary", "Octal", "Hexadecimal", "Decimal" }; 1059 JComboBox userBlockDisplayChoice = new JComboBox(displayChoices); 1060 userBlockDisplayChoice.setSelectedIndex(0); 1061 userBlockDisplayChoice.addActionListener(this); 1062 userBlockDisplayChoice.setEditable(false); 1063 userBlockDisplayChoice.setActionCommand("Display user block as"); 1064 1065 JLabel sizeLabel = new JLabel("Header Size (Bytes): 0"); 1066 jamButton = new JButton("Save User Block"); 1067 jamButton.setActionCommand("Jam user block"); 1068 jamButton.addActionListener(this); 1069 JPanel topPane = new JPanel(); 1070 topPane.setLayout(new BorderLayout(10, 5)); 1071 topPane.add(new JLabel("Display As:"), BorderLayout.WEST); 1072 JPanel topPane0 = new JPanel(); 1073 topPane0.setLayout(new GridLayout(1, 2, 10, 5)); 1074 topPane0.add(userBlockDisplayChoice); 1075 topPane0.add(sizeLabel); 1076 topPane.add(topPane0, BorderLayout.CENTER); 1077 topPane.add(jamButton, BorderLayout.EAST); 1078 1079 JScrollPane scroller = new JScrollPane(userBlockArea); 1080 panel.add(topPane, BorderLayout.NORTH); 1081 panel.add(scroller, BorderLayout.CENTER); 1082 1083 int headSize = 0; 1084 if (userBlock != null) { 1085 headSize = showUserBlockAs(0); 1086 sizeLabel.setText("Header Size (Bytes): " + headSize); 1087 } 1088 else { 1089 userBlockDisplayChoice.setEnabled(false); 1090 } 1091 1092 return panel; 1093 } 1094 1095 private int showUserBlockAs(int radix) { 1096 int headerSize = 0; 1097 1098 if (userBlock == null) { 1099 return 0; 1100 } 1101 1102 String userBlockInfo = null; 1103 if ((radix == 2) || (radix == 8) || (radix == 16) || (radix == 10)) { 1104 StringBuffer sb = new StringBuffer(); 1105 for (headerSize = 0; headerSize < userBlock.length; headerSize++) { 1106 int intValue = (int) userBlock[headerSize]; 1107 if (intValue < 0) { 1108 intValue += 256; 1109 } 1110 else if (intValue == 0) { 1111 break; // null end 1112 } 1113 sb.append(Integer.toString(intValue, radix)); 1114 sb.append(" "); 1115 } 1116 userBlockInfo = sb.toString(); 1117 } 1118 else { 1119 userBlockInfo = new String(userBlock).trim(); 1120 if (userBlockInfo != null) { 1121 headerSize = userBlockInfo.length(); 1122 } 1123 } 1124 1125 userBlockArea.setText(userBlockInfo); 1126 1127 return headerSize; 1128 } 1129 1130 /** 1131 * update attribute value. Currently can only update single data point. 1132 * 1133 * @param newValue 1134 * the string of the new value. 1135 * @param row 1136 * the row number of the selected cell. 1137 * @param col 1138 * the column number of the selected cell. 1139 */ 1140 private void updateAttributeValue(String newValue, int row, int col) { 1141 log.trace("updateAttributeValue:start value={}[{},{}]", newValue, row, col); 1142 1143 String attrName = (String) attrTable.getValueAt(row, 0); 1144 List<?> attrList = null; 1145 try { 1146 attrList = hObject.getMetadata(); 1147 } 1148 catch (Exception ex) { 1149 JOptionPane.showMessageDialog(getOwner(), ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE); 1150 return; 1151 } 1152 1153 Attribute attr = (Attribute) attrList.get(row); 1154 1155 if (col == 1) { // To change attribute value 1156 log.trace("updateAttributeValue: change attribute value"); 1157 Object data = attr.getValue(); 1158 if (data == null) { 1159 return; 1160 } 1161 1162 int array_length = Array.getLength(data); 1163 StringTokenizer st = new StringTokenizer(newValue, ","); 1164 if (st.countTokens() < array_length) { 1165 JOptionPane.showMessageDialog(getOwner(), "More data value needed: " + newValue, getTitle(), 1166 JOptionPane.ERROR_MESSAGE); 1167 return; 1168 } 1169 1170 char NT = ' '; 1171 String cName = data.getClass().getName(); 1172 int cIndex = cName.lastIndexOf("["); 1173 if (cIndex >= 0) { 1174 NT = cName.charAt(cIndex + 1); 1175 } 1176 boolean isUnsigned = attr.isUnsigned(); 1177 log.trace("updateAttributeValue:start array_length={} cName={} NT={} isUnsigned={}", array_length, cName, NT, isUnsigned); 1178 1179 double d = 0; 1180 String theToken = null; 1181 long max = 0, min = 0; 1182 for (int i = 0; i < array_length; i++) { 1183 max = min = 0; 1184 theToken = st.nextToken().trim(); 1185 try { 1186 if (!(Array.get(data, i) instanceof String)) { 1187 d = Double.parseDouble(theToken); 1188 } 1189 } 1190 catch (NumberFormatException ex) { 1191 JOptionPane.showMessageDialog(getOwner(), ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE); 1192 return; 1193 } 1194 1195 if (isUnsigned && (d < 0)) { 1196 JOptionPane.showMessageDialog(getOwner(), "Negative value for unsigned integer: " + theToken, 1197 getTitle(), JOptionPane.ERROR_MESSAGE); 1198 return; 1199 } 1200 1201 switch (NT) { 1202 case 'B': { 1203 if (isUnsigned) { 1204 min = 0; 1205 max = 255; 1206 } 1207 else { 1208 min = Byte.MIN_VALUE; 1209 max = Byte.MAX_VALUE; 1210 } 1211 1212 if ((d > max) || (d < min)) { 1213 JOptionPane.showMessageDialog(getOwner(), "Data is out of range[" + min + ", " + max 1214 + "]: " + theToken, getTitle(), JOptionPane.ERROR_MESSAGE); 1215 } 1216 else { 1217 Array.setByte(data, i, (byte) d); 1218 } 1219 break; 1220 } 1221 case 'S': { 1222 if (isUnsigned) { 1223 min = 0; 1224 max = 65535; 1225 } 1226 else { 1227 min = Short.MIN_VALUE; 1228 max = Short.MAX_VALUE; 1229 } 1230 1231 if ((d > max) || (d < min)) { 1232 JOptionPane.showMessageDialog(getOwner(), "Data is out of range[" + min + ", " + max 1233 + "]: " + theToken, getTitle(), JOptionPane.ERROR_MESSAGE); 1234 } 1235 else { 1236 Array.setShort(data, i, (short) d); 1237 } 1238 break; 1239 } 1240 case 'I': { 1241 if (isUnsigned) { 1242 min = 0; 1243 max = 4294967295L; 1244 } 1245 else { 1246 min = Integer.MIN_VALUE; 1247 max = Integer.MAX_VALUE; 1248 } 1249 1250 if ((d > max) || (d < min)) { 1251 JOptionPane.showMessageDialog(getOwner(), "Data is out of range[" + min + ", " + max 1252 + "]: " + theToken, getTitle(), JOptionPane.ERROR_MESSAGE); 1253 } 1254 else { 1255 Array.setInt(data, i, (int) d); 1256 } 1257 break; 1258 } 1259 case 'J': 1260 long lvalue = 0; 1261 if (isUnsigned) { 1262 if (theToken != null) { 1263 String theValue = theToken; 1264 BigInteger Jmax = new BigInteger("18446744073709551615"); 1265 BigInteger big = new BigInteger(theValue); 1266 if ((big.compareTo(Jmax)>0) || (big.compareTo(BigInteger.ZERO)<0)) { 1267 JOptionPane.showMessageDialog(getOwner(), "Data is out of range[" + min + ", " + max 1268 + "]: " + theToken, getTitle(), JOptionPane.ERROR_MESSAGE); 1269 } 1270 lvalue = big.longValue(); 1271 log.trace("updateAttributeValue: big.longValue={}", lvalue); 1272 Array.setLong(data, i, lvalue); 1273 } 1274 else 1275 Array.set(data, i, (Object)theToken); 1276 } 1277 else { 1278 min = Long.MIN_VALUE; 1279 max = Long.MAX_VALUE; 1280 if ((d > max) || (d < min)) { 1281 JOptionPane.showMessageDialog(getOwner(), "Data is out of range[" + min + ", " + max 1282 + "]: " + theToken, getTitle(), JOptionPane.ERROR_MESSAGE); 1283 } 1284 lvalue = (long)d; 1285 log.trace("updateAttributeValue: longValue={}", lvalue); 1286 Array.setLong(data, i, lvalue); 1287 } 1288 break; 1289 case 'F': 1290 Array.setFloat(data, i, (float) d); 1291 break; 1292 case 'D': 1293 Array.setDouble(data, i, d); 1294 break; 1295 default: 1296 Array.set(data, i, (Object)theToken); 1297 break; 1298 } 1299 } 1300 1301 try { 1302 hObject.getFileFormat().writeAttribute(hObject, attr, true); 1303 } 1304 catch (Exception ex) { 1305 JOptionPane.showMessageDialog(getOwner(), ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE); 1306 return; 1307 } 1308 1309 // update the attribute table 1310 attrTable.setValueAt(attr.toString(", "), row, 1); 1311 } 1312 1313 if ((col == 0) && isH5) { // To change attribute name 1314 log.trace("updateAttributeValue: change attribute name"); 1315 try { 1316 hObject.getFileFormat().renameAttribute(hObject, attrName, newValue); 1317 } 1318 catch (Exception ex) { 1319 JOptionPane.showMessageDialog(getOwner(), ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE); 1320 return; 1321 } 1322 1323 // update the attribute table 1324 attrTable.setValueAt(newValue, row, 0); 1325 } 1326 if (hObject instanceof ScalarDS) { 1327 ScalarDS ds = (ScalarDS) hObject; 1328 try { 1329 log.trace("updateAttributeValue: ScalarDS:updateMetadata"); 1330 ds.updateMetadata(attr); 1331 } 1332 catch (Exception ex) { 1333 JOptionPane.showMessageDialog(getOwner(), ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE); 1334 } 1335 } 1336 else { 1337 log.trace("updateAttributeValue: hObject is not instanceof ScalarDS"); 1338 } 1339 } 1340 1341 private void writeUserBlock() { 1342 if (!isH5) { 1343 return; 1344 } 1345 1346 int blkSize0 = 0; 1347 if (userBlock != null) { 1348 blkSize0 = userBlock.length; 1349 // The super block space is allocated by offset 0, 512, 1024, 2048, 1350 // etc 1351 if (blkSize0 > 0) { 1352 int offset = 512; 1353 while (offset < blkSize0) { 1354 offset *= 2; 1355 } 1356 blkSize0 = offset; 1357 } 1358 } 1359 1360 int blkSize1 = 0; 1361 String userBlockStr = userBlockArea.getText(); 1362 if (userBlockStr == null) { 1363 if (blkSize0 <= 0) { 1364 return; // nothing to write 1365 } 1366 else { 1367 userBlockStr = " "; // want to wipe out old userblock content 1368 } 1369 } 1370 byte buf[] = null; 1371 buf = userBlockStr.getBytes(); 1372 1373 blkSize1 = buf.length; 1374 if (blkSize1 <= blkSize0) { 1375 java.io.RandomAccessFile raf = null; 1376 try { 1377 raf = new java.io.RandomAccessFile(hObject.getFile(), "rw"); 1378 } 1379 catch (Exception ex) { 1380 JOptionPane.showMessageDialog(this, "Can't open output file: " + hObject.getFile(), getTitle(), 1381 JOptionPane.ERROR_MESSAGE); 1382 return; 1383 } 1384 1385 try { 1386 raf.seek(0); 1387 raf.write(buf, 0, buf.length); 1388 raf.seek(buf.length); 1389 if (blkSize0 > buf.length) { 1390 byte[] padBuf = new byte[blkSize0 - buf.length]; 1391 raf.write(padBuf, 0, padBuf.length); 1392 } 1393 } 1394 catch (Exception ex) { 1395 log.debug("raf write:", ex); 1396 } 1397 try { 1398 raf.close(); 1399 } 1400 catch (Exception ex) { 1401 log.debug("raf close:", ex); 1402 } 1403 1404 JOptionPane.showMessageDialog(this, "Saving user block is successful.", getTitle(), 1405 JOptionPane.INFORMATION_MESSAGE); 1406 } 1407 else { 1408 // must rewrite the whole file 1409 // must rewrite the whole file 1410 int op = JOptionPane.showConfirmDialog(this, 1411 "The user block to write is " + blkSize1 + " (bytes),\n" 1412 + "which is larger than the user block space in file " + blkSize0 + " (bytes).\n" 1413 + "To expand the user block, the file must be rewriten.\n\n" 1414 + "Do you want to replace the current file? Click " 1415 + "\n\"Yes\" to replace the current file," + "\n\"No\" to save to a different file, " 1416 + "\n\"Cancel\" to quit without saving the change.\n\n ", getTitle(), 1417 JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE); 1418 1419 if (op == JOptionPane.CANCEL_OPTION) { 1420 return; 1421 } 1422 1423 String fin = hObject.getFile(); 1424 1425 String fout = fin + "~copy.h5"; 1426 if (fin.endsWith(".h5")) { 1427 fout = fin.substring(0, fin.length() - 3) + "~copy.h5"; 1428 } 1429 else if (fin.endsWith(".hdf5")) { 1430 fout = fin.substring(0, fin.length() - 5) + "~copy.h5"; 1431 } 1432 1433 File outFile = null; 1434 1435 if (op == JOptionPane.NO_OPTION) { 1436 JFileChooser fchooser = new JFileChooser(); 1437 fchooser.setFileFilter(DefaultFileFilter.getFileFilterHDF5()); 1438 fchooser.setSelectedFile(new File(fout)); 1439 1440 int returnVal = fchooser.showSaveDialog(this); 1441 if (returnVal != JFileChooser.APPROVE_OPTION) { 1442 return; 1443 } 1444 1445 File choosedFile = fchooser.getSelectedFile(); 1446 if (choosedFile == null) { 1447 return; 1448 } 1449 1450 outFile = choosedFile; 1451 fout = outFile.getAbsolutePath(); 1452 } 1453 else { 1454 outFile = new File(fout); 1455 } 1456 1457 if (!outFile.exists()) { 1458 try { 1459 outFile.createNewFile(); 1460 } 1461 catch (Exception ex) { 1462 JOptionPane.showMessageDialog(this, "Fail to write user block into file. ", getTitle(), 1463 JOptionPane.ERROR_MESSAGE); 1464 return; 1465 } 1466 } 1467 1468 // close the file 1469 ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Close file"); 1470 ((HDFView) viewer).actionPerformed(e); 1471 1472 if (DefaultFileFilter.setHDF5UserBlock(fin, fout, buf)) { 1473 if (op == JOptionPane.NO_OPTION) { 1474 fin = fout; // open the new file 1475 } 1476 else { 1477 File oldFile = new File(fin); 1478 boolean status = oldFile.delete(); 1479 if (status) { 1480 outFile.renameTo(oldFile); 1481 } 1482 else { 1483 JOptionPane.showMessageDialog(this, 1484 "Cannot replace the current file.\nPlease save to a different file.", getTitle(), 1485 JOptionPane.ERROR_MESSAGE); 1486 outFile.delete(); 1487 } 1488 } 1489 } 1490 else { 1491 JOptionPane.showMessageDialog(this, "Fail to write user block into file. ", getTitle(), 1492 JOptionPane.ERROR_MESSAGE); 1493 outFile.delete(); 1494 } 1495 1496 // reopen the file 1497 dispose(); 1498 e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Open file://" + fin); 1499 ((HDFView) viewer).actionPerformed(e); 1500 } 1501 } 1502 1503}