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.Color; 018import java.awt.Dimension; 019import java.awt.GridLayout; 020import java.awt.Point; 021import java.awt.Toolkit; 022import java.awt.event.ActionEvent; 023import java.awt.event.ActionListener; 024import java.awt.event.ItemEvent; 025import java.awt.event.ItemListener; 026import java.awt.event.KeyEvent; 027import java.util.Iterator; 028import java.util.List; 029import java.util.Vector; 030 031import javax.swing.BorderFactory; 032import javax.swing.JButton; 033import javax.swing.JCheckBox; 034import javax.swing.JComboBox; 035import javax.swing.JDialog; 036import javax.swing.JFrame; 037import javax.swing.JLabel; 038import javax.swing.JOptionPane; 039import javax.swing.JPanel; 040import javax.swing.JTextField; 041import javax.swing.border.TitledBorder; 042 043import hdf.object.DataFormat; 044import hdf.object.Datatype; 045import hdf.object.FileFormat; 046import hdf.object.Group; 047import hdf.object.HObject; 048 049/** 050 * NewDatatypeDialog shows a message dialog requesting user input for creating a 051 * new HDF5 datatype. 052 */ 053public class NewDatatypeDialog extends JDialog 054implements ActionListener, ItemListener { 055 private static final long serialVersionUID = -1930736056916611522L; 056 057 private JTextField nameField, stringLengthField; 058 059 @SuppressWarnings("rawtypes") 060 private JComboBox parentChoice, classChoice, sizeChoice, endianChoice; 061 062 private JCheckBox checkUnsigned; 063 064 private boolean isH5; 065 066 /** a list of current groups */ 067 private List<Object> groupList; 068 069 private HObject newObject; 070 071 private FileFormat fileFormat; 072 073 private final Toolkit toolkit; 074 075 /** 076 * Constructs a NewDatatypeDialog with specified list of possible parent 077 * groups. 078 * 079 * @param owner 080 * the owner of the input 081 * @param pGroup 082 * the parent group which the new group is added to. 083 * @param objs 084 * the list of all objects. 085 */ 086 @SuppressWarnings({ "rawtypes", "unchecked" }) 087 public NewDatatypeDialog(JFrame owner, Group pGroup, List<?> objs) { 088 super(owner, "New Datatype...", true); 089 090 toolkit = Toolkit.getDefaultToolkit(); 091 092 newObject = null; 093 094 fileFormat = pGroup.getFileFormat(); 095 isH5 = pGroup.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5)); 096 097 parentChoice = new JComboBox(); 098 groupList = new Vector<Object>(objs.size()); 099 Object obj = null; 100 Iterator<?> iterator = objs.iterator(); 101 while (iterator.hasNext()) { 102 obj = iterator.next(); 103 if (obj instanceof Group) { 104 Group g = (Group) obj; 105 groupList.add(obj); 106 if (g.isRoot()) { 107 parentChoice.addItem(HObject.separator); 108 } 109 else { 110 parentChoice.addItem(g.getPath() + g.getName() + HObject.separator); 111 } 112 } 113 } 114 115 if (pGroup.isRoot()) { 116 parentChoice.setSelectedItem(HObject.separator); 117 } 118 else { 119 parentChoice.setSelectedItem(pGroup.getPath() + pGroup.getName() + HObject.separator); 120 } 121 122 JPanel contentPane = (JPanel) getContentPane(); 123 contentPane.setLayout(new BorderLayout(5, 5)); 124 contentPane.setBorder(BorderFactory.createEmptyBorder(15, 5, 5, 5)); 125 int w = 600 + (ViewProperties.getFontSize() - 12) * 15; 126 int h = 200 + (ViewProperties.getFontSize() - 12) * 10; 127 contentPane.setPreferredSize(new Dimension(w, h)); 128 129 JButton okButton = new JButton(" Ok "); 130 okButton.setName("OK"); 131 okButton.setActionCommand("Ok"); 132 okButton.setMnemonic(KeyEvent.VK_O); 133 okButton.addActionListener(this); 134 135 JButton cancelButton = new JButton("Cancel"); 136 cancelButton.setName("Cancel"); 137 cancelButton.setMnemonic(KeyEvent.VK_C); 138 cancelButton.setActionCommand("Cancel"); 139 cancelButton.addActionListener(this); 140 141 // set OK and CANCEL buttons 142 JPanel buttonPanel = new JPanel(); 143 buttonPanel.add(okButton); 144 buttonPanel.add(cancelButton); 145 contentPane.add(buttonPanel, BorderLayout.SOUTH); 146 147 // set NAME and PARENT GROUP panel 148 JPanel namePanel = new JPanel(); 149 namePanel.setLayout(new BorderLayout(5, 5)); 150 JPanel tmpP = new JPanel(); 151 tmpP.setLayout(new GridLayout(2, 1)); 152 tmpP.add(new JLabel("Datatype name: ")); 153 tmpP.add(new JLabel("Parent group: ")); 154 namePanel.add(tmpP, BorderLayout.WEST); 155 tmpP = new JPanel(); 156 tmpP.setLayout(new GridLayout(2, 1)); 157 nameField = new JTextField(); 158 nameField.setName("dtname"); 159 tmpP.add(nameField); 160 tmpP.add(parentChoice); 161 namePanel.add(tmpP, BorderLayout.CENTER); 162 contentPane.add(namePanel, BorderLayout.NORTH); 163 164 // set DATATYPE 165 JPanel typePanel = new JPanel(); 166 typePanel.setLayout(new GridLayout(2, 4, 15, 3)); 167 TitledBorder border = new TitledBorder("Datatype"); 168 border.setTitleColor(Color.blue); 169 typePanel.setBorder(border); 170 171 stringLengthField = new JTextField("String length"); 172 stringLengthField.setName("dtstringlen"); 173 stringLengthField.setEnabled(false); 174 175 endianChoice = new JComboBox(); 176 endianChoice.setName("dtendian"); 177 classChoice = new JComboBox(); 178 classChoice.setName("dtclass"); 179 sizeChoice = new JComboBox(); 180 sizeChoice.setName("dtsize"); 181 endianChoice.setEnabled(isH5); 182 183 classChoice.addItem("INTEGER"); 184 classChoice.addItem("FLOAT"); 185 classChoice.addItem("CHAR"); 186 187 if (isH5) { 188 classChoice.addItem("STRING"); 189 classChoice.addItem("REFERENCE"); 190 classChoice.addItem("VLEN_INTEGER"); 191 classChoice.addItem("VLEN_FLOAT"); 192 classChoice.addItem("VLEN_STRING"); 193 sizeChoice.addItem("NATIVE"); 194 endianChoice.addItem("NATIVE"); 195 endianChoice.addItem("LITTLE ENDIAN"); 196 endianChoice.addItem("BIG ENDIAN"); 197 } 198 else { 199 sizeChoice.addItem("DEFAULT"); 200 endianChoice.addItem("DEFAULT"); 201 typePanel.add(new JLabel()); 202 } 203 sizeChoice.addItem("8"); 204 sizeChoice.addItem("16"); 205 sizeChoice.addItem("32"); 206 sizeChoice.addItem("64"); 207 208 typePanel.add(new JLabel("Datatype class")); 209 typePanel.add(new JLabel("Size (bits)")); 210 typePanel.add(new JLabel("Byte ordering")); 211 checkUnsigned = new JCheckBox("Unsigned"); 212 checkUnsigned.setName("dtchkunsigned"); 213 typePanel.add(checkUnsigned); 214 215 typePanel.add(classChoice); 216 typePanel.add(sizeChoice); 217 typePanel.add(endianChoice); 218 typePanel.add(stringLengthField); 219 220 contentPane.add(typePanel, BorderLayout.CENTER); 221 222 classChoice.addItemListener(this); 223 sizeChoice.addItemListener(this); 224 225 // locate the H5Property dialog 226 Point l = owner.getLocation(); 227 l.x += 250; 228 l.y += 100; 229 setLocation(l); 230 validate(); 231 pack(); 232 } 233 234 public void actionPerformed(ActionEvent e) { 235 Object source = e.getSource(); 236 String cmd = e.getActionCommand(); 237 238 if (cmd.equals("Ok")) { 239 newObject = createDatatype(); 240 241 if (newObject != null) { 242 dispose(); 243 } 244 } 245 if (cmd.equals("Cancel")) { 246 newObject = null; 247 dispose(); 248 } 249 } 250 251 @SuppressWarnings("unchecked") 252 public void itemStateChanged(ItemEvent e) { 253 Object source = e.getSource(); 254 255 if (source.equals(classChoice)) { 256 int idx = classChoice.getSelectedIndex(); 257 sizeChoice.setSelectedIndex(0); 258 endianChoice.setSelectedIndex(0); 259 stringLengthField.setEnabled(false); 260 261 if ((idx == 0) || (idx == 5)) { 262 sizeChoice.setEnabled(true); 263 endianChoice.setEnabled(isH5); 264 checkUnsigned.setEnabled(true); 265 266 if (sizeChoice.getItemCount() == 3) { 267 sizeChoice.removeItem("32"); 268 sizeChoice.removeItem("64"); 269 sizeChoice.addItem("8"); 270 sizeChoice.addItem("16"); 271 sizeChoice.addItem("32"); 272 sizeChoice.addItem("64"); 273 } 274 } 275 else if ((idx == 1) || (idx == 6)) { 276 sizeChoice.setEnabled(true); 277 endianChoice.setEnabled(isH5); 278 checkUnsigned.setEnabled(false); 279 280 if (sizeChoice.getItemCount() == 5) { 281 sizeChoice.removeItem("16"); 282 sizeChoice.removeItem("8"); 283 } 284 } 285 else if (idx == 2) { 286 sizeChoice.setEnabled(false); 287 endianChoice.setEnabled(isH5); 288 checkUnsigned.setEnabled(true); 289 } 290 else if (idx == 3) { 291 sizeChoice.setEnabled(false); 292 endianChoice.setEnabled(false); 293 checkUnsigned.setEnabled(false); 294 stringLengthField.setEnabled(true); 295 stringLengthField.setText("String length"); 296 } 297 else if (idx == 4) { 298 sizeChoice.setEnabled(false); 299 endianChoice.setEnabled(false); 300 checkUnsigned.setEnabled(false); 301 stringLengthField.setEnabled(false); 302 } 303 else if (idx == 7) { 304 sizeChoice.setEnabled(false); 305 endianChoice.setEnabled(false); 306 checkUnsigned.setEnabled(false); 307 stringLengthField.setEnabled(false); 308 } 309 } 310 else if (source.equals(sizeChoice)) { 311 if (classChoice.getSelectedIndex() == 0) { 312 checkUnsigned.setEnabled(true); 313 } 314 } 315 } 316 317 private HObject createDatatype() { 318 String name = null; 319 Group pgroup = null; 320 boolean isVLen = false; 321 int tclass = -1, tsize = -1, torder = -1, tsign = -1; 322 name = nameField.getText().trim(); 323 if ((name == null) || (name.length() < 1)) { 324 toolkit.beep(); 325 JOptionPane.showMessageDialog(this, 326 "Datatype name is not specified.", 327 getTitle(), 328 JOptionPane.ERROR_MESSAGE); 329 return null; 330 } 331 332 if (name.indexOf(HObject.separator) >= 0) { 333 toolkit.beep(); 334 JOptionPane.showMessageDialog(this, 335 "Datatype name cannot contain path.", 336 getTitle(), 337 JOptionPane.ERROR_MESSAGE); 338 return null; 339 } 340 341 pgroup = (Group) groupList.get(parentChoice.getSelectedIndex()); 342 343 if (pgroup == null) { 344 toolkit.beep(); 345 JOptionPane.showMessageDialog(this, 346 "Parent group is null.", 347 getTitle(), 348 JOptionPane.ERROR_MESSAGE); 349 return null; 350 } 351 352 // set datatype class 353 int idx = classChoice.getSelectedIndex(); 354 if (idx == 0) { 355 tclass = Datatype.CLASS_INTEGER; 356 if (checkUnsigned.isSelected()) { 357 tsign = Datatype.SIGN_NONE; 358 } 359 } 360 else if (idx == 1) { 361 tclass = Datatype.CLASS_FLOAT; 362 } 363 else if (idx == 2) { 364 tclass = Datatype.CLASS_CHAR; 365 if (checkUnsigned.isSelected()) { 366 tsign = Datatype.SIGN_NONE; 367 } 368 } 369 else if (idx == 3) { 370 tclass = Datatype.CLASS_STRING; 371 } 372 else if (idx == 4) { 373 tclass = Datatype.CLASS_REFERENCE; 374 } 375 else if (idx == 5) {; 376 isVLen = true; 377 tclass = Datatype.CLASS_INTEGER; 378 if (checkUnsigned.isSelected()) { 379 tsign = Datatype.SIGN_NONE; 380 } 381 } 382 else if (idx == 6) {; 383 isVLen = true; 384 tclass = Datatype.CLASS_FLOAT; 385 } 386 else if (idx == 7) { 387 isVLen = true; 388 tclass = Datatype.CLASS_STRING; 389 } 390 391 // set datatype size/order 392 idx = sizeChoice.getSelectedIndex(); 393 if (tclass == Datatype.CLASS_STRING) { 394 if (isVLen) { 395 tsize = -1; 396 } 397 else { 398 int stringLength = 0; 399 try { 400 stringLength = Integer.parseInt(stringLengthField.getText()); 401 } 402 catch (NumberFormatException ex) { 403 stringLength = -1; 404 } 405 406 if (stringLength <= 0) { 407 toolkit.beep(); 408 JOptionPane.showMessageDialog(this, 409 "Invalid string length: " + stringLengthField.getText(), 410 getTitle(), 411 JOptionPane.ERROR_MESSAGE); 412 return null; 413 } 414 415 tsize = stringLength; 416 } 417 } 418 else if (tclass == Datatype.CLASS_REFERENCE) { 419 tsize = 1; 420 } 421 else if (idx == 0) { 422 tsize = Datatype.NATIVE; 423 } 424 else if (tclass == Datatype.CLASS_FLOAT) { 425 tsize = idx * 4; 426 } 427 else { 428 tsize = 1 << (idx - 1); 429 } 430 431 if ((tsize == 8) && !isH5 && (tclass == Datatype.CLASS_INTEGER)) { 432 toolkit.beep(); 433 JOptionPane.showMessageDialog(this, 434 "HDF4 does not support 64-bit integer.", 435 getTitle(), 436 JOptionPane.ERROR_MESSAGE); 437 return null; 438 } 439 440 // set order 441 idx = endianChoice.getSelectedIndex(); 442 if (idx == 0) { 443 torder = Datatype.NATIVE; 444 } 445 else if (idx == 1) { 446 torder = Datatype.ORDER_LE; 447 } 448 else { 449 torder = Datatype.ORDER_BE; 450 } 451 452 HObject obj = null; 453 try { 454 String fullPath = HObject.separator; 455 if (pgroup.isRoot()) { 456 fullPath += name; 457 } 458 else { 459 fullPath = pgroup.getPath() + HObject.separator + pgroup.getName() + HObject.separator + name; 460 } 461 Datatype basedatatype = null; 462 if (isVLen) { 463 basedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign); 464 tclass = Datatype.CLASS_VLEN; 465 } 466 Datatype datatype = fileFormat.createDatatype(tclass, tsize, torder, tsign, basedatatype, fullPath); 467 obj = datatype; 468 } 469 catch (Exception ex) { 470 toolkit.beep(); 471 JOptionPane.showMessageDialog(this, 472 ex, 473 getTitle(), 474 JOptionPane.ERROR_MESSAGE); 475 return null; 476 } 477 478 return obj; 479 } 480 481 /** @return the new dataset created. */ 482 public DataFormat getObject() { 483 return newObject; 484 } 485 486 /** @return the parent group of the new dataset. */ 487 public Group getParentGroup() { 488 return (Group) groupList.get(parentChoice.getSelectedIndex()); 489 } 490}