001/***************************************************************************** 002 * Copyright by The HDF Group. * 003 * Copyright by the Board of Trustees of the University of Illinois. * 004 * All rights reserved. * 005 * * 006 * This file is part of the HDF Java Products distribution. * 007 * The full copyright notice, including terms governing use, modification, * 008 * and redistribution, is contained in the files COPYING and Copyright.html. * 009 * COPYING can be found at the root of the source code distribution tree. * 010 * Or, see https://support.hdfgroup.org/products/licenses.html * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.view.dialog; 016 017import java.util.Iterator; 018import java.util.List; 019import java.util.Vector; 020 021import org.slf4j.Logger; 022import org.slf4j.LoggerFactory; 023 024import org.eclipse.swt.SWT; 025import org.eclipse.swt.events.SelectionAdapter; 026import org.eclipse.swt.events.SelectionEvent; 027import org.eclipse.swt.graphics.Font; 028import org.eclipse.swt.layout.GridData; 029import org.eclipse.swt.layout.GridLayout; 030import org.eclipse.swt.widgets.Button; 031import org.eclipse.swt.widgets.Combo; 032import org.eclipse.swt.widgets.Dialog; 033import org.eclipse.swt.widgets.Display; 034import org.eclipse.swt.widgets.Label; 035import org.eclipse.swt.widgets.Shell; 036import org.eclipse.swt.widgets.Text; 037 038import hdf.object.Datatype; 039import hdf.object.FileFormat; 040import hdf.object.Group; 041import hdf.object.HObject; 042import hdf.object.h5.H5Datatype; 043import hdf.view.Tools; 044import hdf.view.ViewProperties; 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 super(parent, SWT.APPLICATION_MODAL); 129 130 try { 131 curFont = new Font( 132 Display.getCurrent(), 133 ViewProperties.getFontType(), 134 ViewProperties.getFontSize(), 135 SWT.NORMAL); 136 } 137 catch (Exception ex) { 138 curFont = null; 139 } 140 141 newObject = null; 142 parentObj = pGroup; 143 objList = objs; 144 145 fileFormat = pGroup.getFileFormat(); 146 isH5 = pGroup.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF5)); 147 } 148 149 /** the new dataset properties to be created. */ 150 public void createDatatypeWidget() { 151 Label label; 152 153 // Create Datatype region 154 org.eclipse.swt.widgets.Group datatypeGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE); 155 datatypeGroup.setFont(curFont); 156 datatypeGroup.setText("Datatype"); 157 datatypeGroup.setLayout(new GridLayout(4, true)); 158 datatypeGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 159 160 useCommittedType = new Button(datatypeGroup, SWT.CHECK); 161 useCommittedType.setFont(curFont); 162 useCommittedType.setText("Use Committed Datatype"); 163 useCommittedType.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); 164 useCommittedType.setEnabled(isH5); 165 166 if(isH5) { 167 label = new Label(datatypeGroup, SWT.LEFT); 168 label.setFont(curFont); 169 label.setText("Committed Datatype: "); 170 171 namedChoice = new Combo(datatypeGroup, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY); 172 namedChoice.setFont(curFont); 173 namedChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 174 namedChoice.addSelectionListener(new SelectionAdapter() { 175 @Override 176 public void widgetSelected(SelectionEvent e) { 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 int idx = classChoice.getSelectionIndex(); 226 sizeChoice.select(0); 227 endianChoice.select(0); 228 lengthField.setEnabled(false); 229 230 if ((idx == 0) || (idx == 6)) { // INTEGER 231 sizeChoice.setEnabled(true); 232 endianChoice.setEnabled(isH5); 233 checkUnsigned.setEnabled(true); 234 235 if (sizeChoice.getItemCount() == 3) { 236 sizeChoice.remove("32"); 237 sizeChoice.remove("64"); 238 sizeChoice.add("8"); 239 sizeChoice.add("16"); 240 sizeChoice.add("32"); 241 sizeChoice.add("64"); 242 } 243 } 244 else if ((idx == 1) || (idx == 7)) { // FLOAT 245 sizeChoice.setEnabled(true); 246 endianChoice.setEnabled(isH5); 247 checkUnsigned.setEnabled(false); 248 249 if (sizeChoice.getItemCount() == 5) { 250 sizeChoice.remove("16"); 251 sizeChoice.remove("8"); 252 } 253 } 254 else if (idx == 2) { // CHAR 255 sizeChoice.setEnabled(false); 256 endianChoice.setEnabled(isH5); 257 checkUnsigned.setEnabled(true); 258 } 259 else if (idx == 3) { // STRING 260 sizeChoice.setEnabled(false); 261 endianChoice.setEnabled(false); 262 checkUnsigned.setEnabled(false); 263 lengthField.setEnabled(true); 264 lengthField.setText("String length"); 265 } 266 else if (idx == 4) { // REFERENCE 267 sizeChoice.setEnabled(false); 268 endianChoice.setEnabled(false); 269 checkUnsigned.setEnabled(false); 270 lengthField.setEnabled(false); 271 } 272 else if (idx == 5) { // ENUM 273 sizeChoice.setEnabled(true); 274 checkUnsigned.setEnabled(true); 275 lengthField.setEnabled(true); 276 lengthField.setText("0=R,1=G,#=TXT,..."); 277 } 278 else if (idx == 8) { 279 sizeChoice.setEnabled(false); 280 endianChoice.setEnabled(false); 281 checkUnsigned.setEnabled(false); 282 lengthField.setEnabled(false); 283 } 284 } 285 }); 286 287 classChoice.add("INTEGER"); 288 classChoice.add("FLOAT"); 289 classChoice.add("CHAR"); 290 291 if(isH5) { 292 classChoice.add("STRING"); 293 classChoice.add("REFERENCE"); 294 classChoice.add("ENUM"); 295 classChoice.add("VLEN_INTEGER"); 296 classChoice.add("VLEN_FLOAT"); 297 classChoice.add("VLEN_STRING"); 298 } 299 300 sizeChoice = new Combo(datatypeGroup, SWT.DROP_DOWN | SWT.READ_ONLY); 301 sizeChoice.setFont(curFont); 302 sizeChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 303 sizeChoice.addSelectionListener(new SelectionAdapter() { 304 @Override 305 public void widgetSelected(SelectionEvent e) { 306 if (classChoice.getSelectionIndex() == 0) { 307 checkUnsigned.setEnabled(true); 308 } 309 } 310 }); 311 312 if(isH5) { 313 sizeChoice.add("NATIVE"); 314 } 315 else { 316 sizeChoice.add("DEFAULT"); 317 } 318 319 sizeChoice.add("8"); 320 sizeChoice.add("16"); 321 sizeChoice.add("32"); 322 sizeChoice.add("64"); 323 324 endianChoice = new Combo(datatypeGroup, SWT.DROP_DOWN | SWT.READ_ONLY); 325 endianChoice.setFont(curFont); 326 endianChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 327 endianChoice.setEnabled(isH5); 328 329 if(isH5) { 330 endianChoice.add("NATIVE"); 331 endianChoice.add("LITTLE ENDIAN"); 332 endianChoice.add("BIG ENDIAN"); 333 } 334 else { 335 endianChoice.add("DEFAULT"); 336 } 337 338 lengthField = new Text(datatypeGroup, SWT.SINGLE | SWT.BORDER); 339 lengthField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 340 lengthField.setFont(curFont); 341 lengthField.setText("String Length"); 342 lengthField.setEnabled(false); 343 344 classChoice.select(0); 345 sizeChoice.select(0); 346 endianChoice.select(0); 347 348 refObject = null; 349 classChoice.setEnabled(true); 350 sizeChoice.setEnabled(true); 351 endianChoice.setEnabled(isH5); 352 checkUnsigned.setEnabled(true); 353 } 354 355 /** 356 * Create the datatype according to the settings. 357 * 358 * @param name 359 * the datatype name 360 * 361 * @return the new object created. 362 */ 363 public Datatype createNewDatatype(String name) { 364 Datatype datatype = null; 365 366 tclass = Datatype.CLASS_NO_CLASS; 367 tsize = Datatype.NATIVE; 368 torder = Datatype.NATIVE; 369 tsign = Datatype.NATIVE; 370 isEnum = false; 371 strEnumMap = null; 372 isVLen = false; 373 isVlenStr = false; 374 375 if (useCommittedType.getSelection()) { 376 datatype = (Datatype)refObject; 377 } 378 else { 379 // idx is set to datatype class 380 int idx = classChoice.getSelectionIndex(); 381 if (idx == 0) { 382 tclass = Datatype.CLASS_INTEGER; 383 if (checkUnsigned.getSelection()) { 384 tsign = Datatype.SIGN_NONE; 385 } 386 } 387 else if (idx == 1) { 388 tclass = Datatype.CLASS_FLOAT; 389 } 390 else if (idx == 2) { 391 tclass = Datatype.CLASS_CHAR; 392 if (checkUnsigned.getSelection()) { 393 tsign = Datatype.SIGN_NONE; 394 } 395 } 396 else if (idx == 3) { 397 tclass = Datatype.CLASS_STRING; 398 } 399 else if (idx == 4) { 400 tclass = Datatype.CLASS_REFERENCE; 401 } 402 else if (idx == 5) { 403 isEnum = true; 404 tclass = Datatype.CLASS_ENUM; 405 } 406 else if (idx == 6) { 407 isVLen = true; 408 tclass = Datatype.CLASS_INTEGER; 409 if (checkUnsigned.getSelection()) { 410 tsign = Datatype.SIGN_NONE; 411 } 412 } 413 else if (idx == 7) { 414 isVLen = true; 415 tclass = Datatype.CLASS_FLOAT; 416 } 417 else if (idx == 8) { 418 tclass = Datatype.CLASS_STRING; 419 isVlenStr = true; 420 tsize = -1; 421 } 422 423 // idx is set to datatype size 424 idx = sizeChoice.getSelectionIndex(); 425 if (tclass == Datatype.CLASS_STRING) { 426 if (!isVlenStr) { 427 int stringLength = 0; 428 try { 429 stringLength = Integer.parseInt(lengthField.getText()); 430 } 431 catch (NumberFormatException ex) { 432 stringLength = -1; 433 } 434 435 if (stringLength <= 0) { 436 shell.getDisplay().beep(); 437 Tools.showError(shell, "Create", "Invalid string length: " + lengthField.getText()); 438 return null; 439 } 440 tsize = stringLength; 441 } 442 } 443 else if (tclass == Datatype.CLASS_REFERENCE) { 444 tsize = 1; 445 torder = Datatype.NATIVE; 446 } 447 else if (idx == 0) { 448 tsize = Datatype.NATIVE; 449 } 450 else if (tclass == Datatype.CLASS_FLOAT) { 451 tsize = idx * 4; 452 } 453 else if (tclass == Datatype.CLASS_INTEGER || tclass == Datatype.CLASS_ENUM) { 454 // Note that idx == 0 is set to either 455 // "NATIVE" if isH5 is true 456 // "DEFAULT" otherwise 457 switch(idx) { 458 case 1: 459 tsize = 1; 460 break; 461 case 2: 462 tsize = 2; 463 break; 464 case 3: 465 tsize = 4; 466 break; 467 case 4: 468 tsize = 8; 469 break; 470 default: 471 tsize = -1; 472 break; 473 } 474 log.trace("CLASS_INTEGER or CLASS_ENUM: tsize={}", tsize); 475 } 476 else if (tclass == Datatype.CLASS_FLOAT) { 477 tsize = (idx + 1) * 4; 478 log.trace("CLASS_FLOAT: tsize={}", tsize); 479 } 480 else { 481 tsize = 1 << (idx - 1); 482 } 483 484 if ((tsize == 8) && !isH5 && (tclass == Datatype.CLASS_INTEGER)) { 485 shell.getDisplay().beep(); 486 Tools.showError(shell, "Create", "HDF4 does not support 64-bit integer."); 487 return null; 488 } 489 490 // set order 491 idx = endianChoice.getSelectionIndex(); 492 if (idx == 0) { 493 torder = Datatype.NATIVE; 494 } 495 else if (idx == 1) { 496 torder = Datatype.ORDER_LE; 497 } 498 else { 499 torder = Datatype.ORDER_BE; 500 } 501 502 Datatype thedatatype = null; 503 try { 504 Datatype basedatatype = null; 505 if (isVLen) { 506 basedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign); 507 tclass = Datatype.CLASS_VLEN; 508 thedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign, basedatatype); 509 } 510 else if (isEnum && isH5) { 511 strEnumMap = lengthField.getText(); 512 if ((strEnumMap == null) || (strEnumMap.length() < 1) || strEnumMap.endsWith("...")) { 513 shell.getDisplay().beep(); 514 Tools.showError(shell, "Create", "Invalid member values: " + lengthField.getText()); 515 return null; 516 } 517 log.trace("CLASS_ENUM enumStr={}", strEnumMap); 518 519 thedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign); 520 thedatatype.setEnumMembers(strEnumMap); 521 } 522 else 523 thedatatype = fileFormat.createDatatype(tclass, tsize, torder, tsign); 524 525 if(isH5) 526 datatype = fileFormat.createNamedDatatype(thedatatype, name); 527 else 528 datatype = thedatatype; 529 } 530 catch (Exception ex) { 531 shell.getDisplay().beep(); 532 Tools.showError(shell, "Create", ex.getMessage()); 533 return null; 534 } 535 } 536 return datatype; 537 } 538 539 /** @return the new object created. */ 540 public HObject getObject() { 541 return newObject; 542 } 543 544 /** @return the parent group of the new dataset. */ 545 public Group getParentGroup() { 546 return (Group) parentObj; 547 } 548}