001/***************************************************************************** 002 * Copyright by The HDF Group. * 003 * Copyright by the Board of Trustees of the University of Illinois. * 004 * All rights reserved. * 005 * * 006 * This file is part of the HDF Java Products distribution. * 007 * The full copyright notice, including terms governing use, modification, * 008 * and redistribution, is contained in the COPYING file, which can be found * 009 * at the root of the source code distribution tree, * 010 * or in https://www.hdfgroup.org/licenses. * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.view.dialog; 016 017import java.util.Iterator; 018import java.util.List; 019import java.util.Vector; 020 021import hdf.object.Datatype; 022import hdf.object.FileFormat; 023import hdf.object.Group; 024import hdf.object.HObject; 025import hdf.object.h5.H5Datatype; 026import hdf.view.Tools; 027import hdf.view.ViewProperties; 028 029import org.slf4j.Logger; 030import org.slf4j.LoggerFactory; 031 032import org.eclipse.swt.SWT; 033import org.eclipse.swt.events.SelectionAdapter; 034import org.eclipse.swt.events.SelectionEvent; 035import org.eclipse.swt.graphics.Font; 036import org.eclipse.swt.layout.GridData; 037import org.eclipse.swt.layout.GridLayout; 038import org.eclipse.swt.widgets.Button; 039import org.eclipse.swt.widgets.Combo; 040import org.eclipse.swt.widgets.Dialog; 041import org.eclipse.swt.widgets.Display; 042import org.eclipse.swt.widgets.Label; 043import org.eclipse.swt.widgets.Shell; 044import org.eclipse.swt.widgets.Text; 045 046/** 047 * NewDataDialog is an intermediate class for creating data types. 048 */ 049public class NewDataObjectDialog extends Dialog { 050 051 private static final Logger log = LoggerFactory.getLogger(NewDataObjectDialog.class); 052 053 /** the visual shell for the dialog */ 054 protected Shell shell; 055 056 /** the current font */ 057 protected Font curFont; 058 059 /** the object which the this object is attached */ 060 protected HObject parentObj; 061 062 /** the object referenced */ 063 protected HObject refObject; 064 065 /** the object created */ 066 protected HObject newObject; 067 068 /** TextField for entering the length of the data array or string. */ 069 protected Text lengthField; 070 071 /** The Choice of the datatypes */ 072 /** The named datatype combobox for the object */ 073 protected Combo namedChoice; 074 /** The class combobox for the object */ 075 protected Combo classChoice; 076 /** The size combobox for the object */ 077 protected Combo sizeChoice; 078 /** The endianess combobox for the object */ 079 protected Combo endianChoice; 080 081 /** The Choice of the object list */ 082 /** The committed datatype button for the object */ 083 protected Button useCommittedType; 084 /** The unsigned data button for the object */ 085 protected Button checkUnsigned; 086 /** The list of objects for the object */ 087 protected List<?> objList; 088 /** The list of datatypes for the object */ 089 protected List<Datatype> namedList; 090 /** The length label for the object */ 091 protected Label arrayLengthLabel; 092 093 /** The attributes of the datatype */ 094 /** The default class for the object */ 095 public int tclass = Datatype.CLASS_NO_CLASS; 096 /** The default size for the object */ 097 public int tsize = Datatype.NATIVE; 098 /** The default byte order for the object */ 099 public int torder = Datatype.NATIVE; 100 /** The default sign for the object */ 101 public int tsign = Datatype.NATIVE; 102 /** If the object is an enum object */ 103 public boolean isEnum = false; 104 /** The enum mapping for the object */ 105 public String strEnumMap = null; 106 /** If the object is a variable length data object */ 107 public boolean isVLen = false; 108 /** If the object is a variable length string */ 109 public boolean isVlenStr = false; 110 111 /** The file format associated with this object */ 112 protected FileFormat fileFormat; 113 114 /** If the object should be attached to a hdf5 object */ 115 protected boolean isH5; 116 117 /** 118 * The NewDataObjectDialog constructor. 119 * 120 * @param parent 121 * the dialog parent shell 122 * @param pGroup 123 * the dialog parent group object 124 * @param objs 125 * the list of objects 126 */ 127 public NewDataObjectDialog(Shell parent, HObject pGroup, List<?> objs) 128 { 129 super(parent, SWT.APPLICATION_MODAL); 130 131 try { 132 curFont = new Font(Display.getCurrent(), ViewProperties.getFontType(), 133 ViewProperties.getFontSize(), SWT.NORMAL); 134 } 135 catch (Exception ex) { 136 curFont = null; 137 } 138 139 newObject = null; 140 parentObj = pGroup; 141 objList = objs; 142 143 fileFormat = pGroup.getFileFormat(); 144 isH5 = pGroup.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5)); 145 } 146 147 /** the new dataset properties to be created. */ 148 public void createDatatypeWidget() 149 { 150 Label label; 151 152 // Create Datatype region 153 org.eclipse.swt.widgets.Group datatypeGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE); 154 datatypeGroup.setFont(curFont); 155 datatypeGroup.setText("Datatype"); 156 datatypeGroup.setLayout(new GridLayout(4, true)); 157 datatypeGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 158 159 useCommittedType = new Button(datatypeGroup, SWT.CHECK); 160 useCommittedType.setFont(curFont); 161 useCommittedType.setText("Use Committed Datatype"); 162 useCommittedType.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); 163 useCommittedType.setEnabled(isH5); 164 165 if (isH5) { 166 label = new Label(datatypeGroup, SWT.LEFT); 167 label.setFont(curFont); 168 label.setText("Committed Datatype: "); 169 170 namedChoice = new Combo(datatypeGroup, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY); 171 namedChoice.setFont(curFont); 172 namedChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 173 namedChoice.addSelectionListener(new SelectionAdapter() { 174 @Override 175 public void widgetSelected(SelectionEvent e) 176 { 177 refObject = namedList.get(namedChoice.getSelectionIndex()); 178 } 179 }); 180 181 // Dummy label 182 label = new Label(datatypeGroup, SWT.LEFT); 183 label.setFont(curFont); 184 label.setText(""); 185 186 namedList = new Vector<>(objList.size()); 187 Object obj = null; 188 Iterator<?> iterator = objList.iterator(); 189 while (iterator.hasNext()) { 190 obj = iterator.next(); 191 if (obj instanceof Datatype) { 192 H5Datatype ndt = (H5Datatype)obj; 193 namedList.add(ndt); 194 namedChoice.add(((Datatype)obj).getFullName()); 195 } 196 } 197 198 if (refObject != null) 199 namedChoice.select(namedChoice.indexOf(((Datatype)refObject).getFullName())); 200 } 201 202 label = new Label(datatypeGroup, SWT.LEFT); 203 label.setFont(curFont); 204 label.setText("Datatype Class"); 205 206 label = new Label(datatypeGroup, SWT.LEFT); 207 label.setFont(curFont); 208 label.setText("Size (bits)"); 209 210 label = new Label(datatypeGroup, SWT.LEFT); 211 label.setFont(curFont); 212 label.setText("Byte Ordering"); 213 214 checkUnsigned = new Button(datatypeGroup, SWT.CHECK); 215 checkUnsigned.setFont(curFont); 216 checkUnsigned.setText("Unsigned"); 217 checkUnsigned.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); 218 219 classChoice = new Combo(datatypeGroup, SWT.DROP_DOWN | SWT.READ_ONLY); 220 classChoice.setFont(curFont); 221 classChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 222 classChoice.addSelectionListener(new SelectionAdapter() { 223 @Override 224 public void widgetSelected(SelectionEvent e) 225 { 226 int idx = classChoice.getSelectionIndex(); 227 sizeChoice.select(0); 228 endianChoice.select(0); 229 lengthField.setEnabled(false); 230 231 if ((idx == 0) || (idx == 6)) { // INTEGER 232 sizeChoice.setEnabled(true); 233 endianChoice.setEnabled(isH5); 234 checkUnsigned.setEnabled(true); 235 236 if (sizeChoice.getItemCount() == 3) { 237 sizeChoice.remove("32"); 238 sizeChoice.remove("64"); 239 sizeChoice.add("8"); 240 sizeChoice.add("16"); 241 sizeChoice.add("32"); 242 sizeChoice.add("64"); 243 } 244 } 245 else if ((idx == 1) || (idx == 7)) { // FLOAT 246 sizeChoice.setEnabled(true); 247 endianChoice.setEnabled(isH5); 248 checkUnsigned.setEnabled(false); 249 250 if (sizeChoice.getItemCount() == 5) { 251 sizeChoice.remove("16"); 252 sizeChoice.remove("8"); 253 } 254 } 255 else if (idx == 2) { // CHAR 256 sizeChoice.setEnabled(false); 257 endianChoice.setEnabled(isH5); 258 checkUnsigned.setEnabled(true); 259 } 260 else if (idx == 3) { // STRING 261 sizeChoice.setEnabled(false); 262 endianChoice.setEnabled(false); 263 checkUnsigned.setEnabled(false); 264 lengthField.setEnabled(true); 265 lengthField.setText("String length"); 266 } 267 else if (idx == 4) { // REFERENCE 268 sizeChoice.setEnabled(false); 269 endianChoice.setEnabled(false); 270 checkUnsigned.setEnabled(false); 271 lengthField.setEnabled(false); 272 } 273 else if (idx == 5) { // ENUM 274 sizeChoice.setEnabled(true); 275 checkUnsigned.setEnabled(true); 276 lengthField.setEnabled(true); 277 lengthField.setText("0=R,1=G,#=TXT,..."); 278 } 279 else if (idx == 8) { 280 sizeChoice.setEnabled(false); 281 endianChoice.setEnabled(false); 282 checkUnsigned.setEnabled(false); 283 lengthField.setEnabled(false); 284 } 285 } 286 }); 287 288 classChoice.add("INTEGER"); 289 classChoice.add("FLOAT"); 290 classChoice.add("CHAR"); 291 292 if (isH5) { 293 classChoice.add("STRING"); 294 classChoice.add("REFERENCE"); 295 classChoice.add("ENUM"); 296 classChoice.add("VLEN_INTEGER"); 297 classChoice.add("VLEN_FLOAT"); 298 classChoice.add("VLEN_STRING"); 299 } 300 301 sizeChoice = new Combo(datatypeGroup, SWT.DROP_DOWN | SWT.READ_ONLY); 302 sizeChoice.setFont(curFont); 303 sizeChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 304 sizeChoice.addSelectionListener(new SelectionAdapter() { 305 @Override 306 public void widgetSelected(SelectionEvent e) 307 { 308 if (classChoice.getSelectionIndex() == 0) { 309 checkUnsigned.setEnabled(true); 310 } 311 } 312 }); 313 314 if (isH5) { 315 sizeChoice.add("NATIVE"); 316 } 317 else { 318 sizeChoice.add("DEFAULT"); 319 } 320 321 sizeChoice.add("8"); 322 sizeChoice.add("16"); 323 sizeChoice.add("32"); 324 sizeChoice.add("64"); 325 326 endianChoice = new Combo(datatypeGroup, SWT.DROP_DOWN | SWT.READ_ONLY); 327 endianChoice.setFont(curFont); 328 endianChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 329 endianChoice.setEnabled(isH5); 330 331 if (isH5) { 332 endianChoice.add("NATIVE"); 333 endianChoice.add("LITTLE ENDIAN"); 334 endianChoice.add("BIG ENDIAN"); 335 } 336 else { 337 endianChoice.add("DEFAULT"); 338 } 339 340 lengthField = new Text(datatypeGroup, SWT.SINGLE | SWT.BORDER); 341 lengthField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 342 lengthField.setFont(curFont); 343 lengthField.setText("String Length"); 344 lengthField.setEnabled(false); 345 346 classChoice.select(0); 347 sizeChoice.select(0); 348 endianChoice.select(0); 349 350 refObject = null; 351 classChoice.setEnabled(true); 352 sizeChoice.setEnabled(true); 353 endianChoice.setEnabled(isH5); 354 checkUnsigned.setEnabled(true); 355 } 356 357 /** 358 * Create the datatype according to the settings. 359 * 360 * @param name 361 * the datatype name 362 * 363 * @return the new object created. 364 */ 365 public Datatype createNewDatatype(String name) 366 { 367 Datatype datatype = null; 368 369 tclass = Datatype.CLASS_NO_CLASS; 370 tsize = Datatype.NATIVE; 371 torder = Datatype.NATIVE; 372 tsign = Datatype.NATIVE; 373 isEnum = false; 374 strEnumMap = null; 375 isVLen = false; 376 isVlenStr = false; 377 378 if (useCommittedType.getSelection()) { 379 datatype = (Datatype)refObject; 380 } 381 else { 382 // idx is set to datatype class 383 int idx = classChoice.getSelectionIndex(); 384 if (idx == 0) { 385 tclass = Datatype.CLASS_INTEGER; 386 if (checkUnsigned.getSelection()) { 387 tsign = Datatype.SIGN_NONE; 388 } 389 } 390 else if (idx == 1) { 391 tclass = Datatype.CLASS_FLOAT; 392 } 393 else if (idx == 2) { 394 tclass = Datatype.CLASS_CHAR; 395 if (checkUnsigned.getSelection()) { 396 tsign = Datatype.SIGN_NONE; 397 } 398 } 399 else if (idx == 3) { 400 tclass = Datatype.CLASS_STRING; 401 } 402 else if (idx == 4) { 403 tclass = Datatype.CLASS_REFERENCE; 404 } 405 else if (idx == 5) { 406 isEnum = true; 407 tclass = Datatype.CLASS_ENUM; 408 } 409 else if (idx == 6) { 410 isVLen = true; 411 tclass = Datatype.CLASS_INTEGER; 412 if (checkUnsigned.getSelection()) { 413 tsign = Datatype.SIGN_NONE; 414 } 415 } 416 else if (idx == 7) { 417 isVLen = true; 418 tclass = Datatype.CLASS_FLOAT; 419 } 420 else if (idx == 8) { 421 tclass = Datatype.CLASS_STRING; 422 isVlenStr = true; 423 tsize = -1; 424 } 425 426 // idx is set to datatype size 427 idx = sizeChoice.getSelectionIndex(); 428 if (tclass == Datatype.CLASS_STRING) { 429 if (!isVlenStr) { 430 int stringLength = 0; 431 try { 432 stringLength = Integer.parseInt(lengthField.getText()); 433 } 434 catch (NumberFormatException ex) { 435 stringLength = -1; 436 } 437 438 if (stringLength <= 0) { 439 shell.getDisplay().beep(); 440 Tools.showError(shell, "Create", "Invalid string length: " + lengthField.getText()); 441 return null; 442 } 443 tsize = stringLength; 444 } 445 } 446 else if (tclass == Datatype.CLASS_REFERENCE) { 447 tsize = 1; 448 torder = Datatype.NATIVE; 449 } 450 else if (idx == 0) { 451 tsize = Datatype.NATIVE; 452 } 453 else if (tclass == Datatype.CLASS_FLOAT) { 454 tsize = idx * 4; 455 } 456 else if (tclass == Datatype.CLASS_INTEGER || tclass == Datatype.CLASS_ENUM) { 457 // Note that idx == 0 is set to either 458 // "NATIVE" if isH5 is true 459 // "DEFAULT" otherwise 460 switch (idx) { 461 case 1: 462 tsize = 1; 463 break; 464 case 2: 465 tsize = 2; 466 break; 467 case 3: 468 tsize = 4; 469 break; 470 case 4: 471 tsize = 8; 472 break; 473 default: 474 tsize = -1; 475 break; 476 } 477 log.trace("CLASS_INTEGER or CLASS_ENUM: tsize={}", tsize); 478 } 479 else if (tclass == Datatype.CLASS_FLOAT) { 480 tsize = (idx + 1) * 4; 481 log.trace("CLASS_FLOAT: tsize={}", tsize); 482 } 483 else { 484 tsize = 1 << (idx - 1); 485 } 486 487 if ((tsize == 8) && !isH5 && (tclass == Datatype.CLASS_INTEGER)) { 488 shell.getDisplay().beep(); 489 Tools.showError(shell, "Create", "HDF4 does not support 64-bit integer."); 490 return null; 491 } 492 493 // set order 494 idx = endianChoice.getSelectionIndex(); 495 if (idx == 0) { 496 torder = Datatype.NATIVE; 497 } 498 else if (idx == 1) { 499 torder = Datatype.ORDER_LE; 500 } 501 else { 502 torder = Datatype.ORDER_BE; 503 } 504 505 Datatype thedatatype = null; 506 try { 507 Datatype basedatatype = null; 508 if (isVLen) { 509 basedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign); 510 tclass = Datatype.CLASS_VLEN; 511 thedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign, basedatatype); 512 } 513 else if (isEnum && isH5) { 514 strEnumMap = lengthField.getText(); 515 if ((strEnumMap == null) || (strEnumMap.length() < 1) || strEnumMap.endsWith("...")) { 516 shell.getDisplay().beep(); 517 Tools.showError(shell, "Create", "Invalid member values: " + lengthField.getText()); 518 return null; 519 } 520 log.trace("CLASS_ENUM enumStr={}", strEnumMap); 521 522 thedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign); 523 thedatatype.setEnumMembers(strEnumMap); 524 } 525 else 526 thedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign); 527 528 if (isH5) 529 datatype = fileFormat.createNamedDatatype(thedatatype, name); 530 else 531 datatype = thedatatype; 532 } 533 catch (Exception ex) { 534 shell.getDisplay().beep(); 535 Tools.showError(shell, "Create", ex.getMessage()); 536 return null; 537 } 538 } 539 return datatype; 540 } 541 542 /** 543 * Get the new object created. 544 * 545 * @return the new object created. 546 */ 547 public HObject getObject() { return newObject; } 548 549 /** 550 * Get the parent group of the new dataset. 551 * 552 * @return the parent group of the new dataset. 553 */ 554 public Group getParentGroup() { return (Group)parentObj; } 555}