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