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.ArrayList; 018import java.util.Iterator; 019import java.util.List; 020 021import hdf.object.Group; 022import hdf.object.HObject; 023import hdf.view.Tools; 024import hdf.view.ViewProperties; 025 026import org.eclipse.swt.SWT; 027import org.eclipse.swt.events.DisposeEvent; 028import org.eclipse.swt.events.DisposeListener; 029import org.eclipse.swt.events.SelectionAdapter; 030import org.eclipse.swt.events.SelectionEvent; 031import org.eclipse.swt.events.VerifyEvent; 032import org.eclipse.swt.events.VerifyListener; 033import org.eclipse.swt.graphics.Point; 034import org.eclipse.swt.graphics.Rectangle; 035import org.eclipse.swt.layout.GridData; 036import org.eclipse.swt.layout.GridLayout; 037import org.eclipse.swt.widgets.Button; 038import org.eclipse.swt.widgets.Combo; 039import org.eclipse.swt.widgets.Composite; 040import org.eclipse.swt.widgets.Display; 041import org.eclipse.swt.widgets.Label; 042import org.eclipse.swt.widgets.Shell; 043import org.eclipse.swt.widgets.Text; 044 045/** 046 * NewGroupDialog shows a message dialog requesting user input for creating a new HDF4/5 group. 047 * 048 * @author Jordan T. Henderson 049 * @version 2.4 12/30/2015 050 */ 051public class NewGroupDialog extends NewDataObjectDialog { 052 053 /* Used to restore original size after click "less" button */ 054 private Point originalSize; 055 056 private Text nameField; 057 private Text compactField; 058 private Text indexedField; 059 060 private Combo parentChoice; 061 private Combo orderFlags; 062 063 private Button useCreationOrder; 064 private Button setLinkStorage; 065 private Button creationOrderHelpButton; 066 private Button storageTypeHelpButton; 067 private Button okButton; 068 private Button cancelButton; 069 private Button moreButton; 070 071 private Composite moreOptionsComposite; 072 private Composite creationOrderComposite; 073 private Composite storageTypeComposite; 074 private Composite dummyComposite; 075 private Composite buttonComposite; 076 077 private List<Group> groupList; 078 079 private int creationOrder; 080 081 private boolean moreOptionsEnabled; 082 083 /** 084 * Constructs a NewGroupDialog with specified list of possible parent groups. 085 * 086 * @param parent 087 * the parent shell of the dialog 088 * @param pGroup 089 * the parent group which the new group is added to. 090 * @param objs 091 * the list of all objects. 092 */ 093 public NewGroupDialog(Shell parent, Group pGroup, List<?> objs) 094 { 095 super(parent, pGroup, objs); 096 097 moreOptionsEnabled = false; 098 } 099 100 /** 101 * Open the NewGroupDialog for adding a new group. 102 */ 103 public void open() 104 { 105 Shell parent = getParent(); 106 shell = new Shell(parent, SWT.SHELL_TRIM | SWT.APPLICATION_MODAL); 107 shell.setFont(curFont); 108 shell.setText("New Group..."); 109 shell.setImages(ViewProperties.getHdfIcons()); 110 GridLayout layout = new GridLayout(1, false); 111 layout.verticalSpacing = 0; 112 shell.setLayout(layout); 113 114 Composite fieldComposite = new Composite(shell, SWT.NONE); 115 fieldComposite.setLayout(new GridLayout(2, false)); 116 fieldComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 117 118 Label groupNameLabel = new Label(fieldComposite, SWT.LEFT); 119 groupNameLabel.setFont(curFont); 120 groupNameLabel.setText("Group name:"); 121 122 nameField = new Text(fieldComposite, SWT.SINGLE | SWT.BORDER); 123 nameField.setFont(curFont); 124 GridData fieldData = new GridData(SWT.FILL, SWT.FILL, true, false); 125 fieldData.minimumWidth = 250; 126 nameField.setLayoutData(fieldData); 127 128 Label parentGroupLabel = new Label(fieldComposite, SWT.LEFT); 129 parentGroupLabel.setFont(curFont); 130 parentGroupLabel.setText("Parent group:"); 131 parentGroupLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); 132 133 parentChoice = new Combo(fieldComposite, SWT.DROP_DOWN | SWT.BORDER | SWT.READ_ONLY); 134 parentChoice.setFont(curFont); 135 parentChoice.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 136 parentChoice.addSelectionListener(new SelectionAdapter() { 137 @Override 138 public void widgetSelected(SelectionEvent e) 139 { 140 parentObj = groupList.get(parentChoice.getSelectionIndex()); 141 } 142 }); 143 144 groupList = new ArrayList<>(); 145 Object obj = null; 146 Iterator<?> iterator = objList.iterator(); 147 while (iterator.hasNext()) { 148 obj = iterator.next(); 149 if (obj instanceof Group) { 150 Group g = (Group)obj; 151 groupList.add(g); 152 if (g.isRoot()) { 153 parentChoice.add(HObject.SEPARATOR); 154 } 155 else { 156 parentChoice.add(g.getPath() + g.getName() + HObject.SEPARATOR); 157 } 158 } 159 } 160 161 if (((Group)parentObj).isRoot()) { 162 parentChoice.select(parentChoice.indexOf(HObject.SEPARATOR)); 163 } 164 else { 165 parentChoice.select( 166 parentChoice.indexOf(parentObj.getPath() + parentObj.getName() + HObject.SEPARATOR)); 167 } 168 169 // Only add "More" button if file is H5 type 170 if (isH5) { 171 moreOptionsComposite = new Composite(shell, SWT.NONE); 172 moreOptionsComposite.setLayout(new GridLayout(2, false)); 173 moreOptionsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); 174 175 moreButton = new Button(moreOptionsComposite, SWT.PUSH); 176 moreButton.setFont(curFont); 177 moreButton.setText(" More "); 178 moreButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false)); 179 moreButton.addSelectionListener(new SelectionAdapter() { 180 @Override 181 public void widgetSelected(SelectionEvent e) 182 { 183 moreOptionsEnabled = !moreOptionsEnabled; 184 185 if (moreOptionsEnabled) { 186 addMoreOptions(); 187 } 188 else { 189 removeMoreOptions(); 190 } 191 } 192 }); 193 194 dummyComposite = new Composite(moreOptionsComposite, SWT.NONE); 195 dummyComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 196 } 197 else { 198 // Add dummy label to take up space as dialog is resized 199 new Label(shell, SWT.NONE).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 200 } 201 202 buttonComposite = new Composite(shell, SWT.NONE); 203 buttonComposite.setLayout(new GridLayout(2, true)); 204 buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); 205 206 okButton = new Button(buttonComposite, SWT.PUSH); 207 okButton.setFont(curFont); 208 okButton.setText(" &OK "); 209 okButton.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); 210 okButton.addSelectionListener(new SelectionAdapter() { 211 @Override 212 public void widgetSelected(SelectionEvent e) 213 { 214 newObject = create(); 215 if (newObject != null) { 216 shell.dispose(); 217 } 218 } 219 }); 220 221 cancelButton = new Button(buttonComposite, SWT.PUSH); 222 cancelButton.setFont(curFont); 223 cancelButton.setText(" &Cancel "); 224 cancelButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false)); 225 cancelButton.addSelectionListener(new SelectionAdapter() { 226 @Override 227 public void widgetSelected(SelectionEvent e) 228 { 229 newObject = null; 230 shell.dispose(); 231 } 232 }); 233 234 shell.pack(); 235 236 shell.addDisposeListener(new DisposeListener() { 237 @Override 238 public void widgetDisposed(DisposeEvent e) 239 { 240 if (curFont != null) 241 curFont.dispose(); 242 } 243 }); 244 245 shell.setMinimumSize(shell.computeSize(SWT.DEFAULT, SWT.DEFAULT)); 246 247 originalSize = shell.getSize(); 248 249 Rectangle parentBounds = parent.getBounds(); 250 Point shellSize = shell.getSize(); 251 shell.setLocation((parentBounds.x + (parentBounds.width / 2)) - (shellSize.x / 2), 252 (parentBounds.y + (parentBounds.height / 2)) - (shellSize.y / 2)); 253 254 shell.open(); 255 256 Display display = shell.getDisplay(); 257 while (!shell.isDisposed()) 258 if (!display.readAndDispatch()) 259 display.sleep(); 260 } 261 262 private HObject create() 263 { 264 String name = null; 265 Group pgroup = null; 266 long gcpl = 0; 267 268 name = nameField.getText(); 269 if (name == null || name.length() == 0) { 270 shell.getDisplay().beep(); 271 Tools.showError(shell, "Create", "Group name is not specified."); 272 return null; 273 } 274 275 if (name.indexOf(HObject.SEPARATOR) >= 0) { 276 shell.getDisplay().beep(); 277 Tools.showError(shell, "Create", "Group name cannot contain path."); 278 return null; 279 } 280 281 pgroup = groupList.get(parentChoice.getSelectionIndex()); 282 283 if (pgroup == null) { 284 shell.getDisplay().beep(); 285 Tools.showError(shell, "Create", "Parent group is null."); 286 return null; 287 } 288 289 Group obj = null; 290 291 if (orderFlags != null && orderFlags.isEnabled()) { 292 String order = orderFlags.getItem(orderFlags.getSelectionIndex()); 293 if (order.equals("Tracked")) 294 creationOrder = Group.CRT_ORDER_TRACKED; 295 else if (order.equals("Tracked+Indexed")) 296 creationOrder = Group.CRT_ORDER_INDEXED; 297 } 298 else 299 creationOrder = 0; 300 301 if ((orderFlags != null) && ((orderFlags.isEnabled()) || (setLinkStorage.getSelection()))) { 302 int maxCompact = Integer.parseInt(compactField.getText()); 303 int minDense = Integer.parseInt(indexedField.getText()); 304 305 if ((maxCompact <= 0) || (maxCompact > 65536) || (minDense > 65536)) { 306 shell.getDisplay().beep(); 307 Tools.showError(shell, "Create", "Max Compact and Min Indexed should be > 0 and < 65536."); 308 return null; 309 } 310 311 if (maxCompact < minDense) { 312 shell.getDisplay().beep(); 313 Tools.showError(shell, "Create", "Min Indexed should be <= Max Compact"); 314 return null; 315 } 316 317 try { 318 gcpl = fileFormat.createGcpl(creationOrder, maxCompact, minDense); 319 } 320 catch (Exception ex) { 321 ex.printStackTrace(); 322 } 323 } 324 325 try { 326 if (isH5) 327 obj = fileFormat.createGroup(name, pgroup, 0, gcpl); 328 else 329 obj = fileFormat.createGroup(name, pgroup); 330 } 331 catch (Exception ex) { 332 shell.getDisplay().beep(); 333 Tools.showError(shell, "Create", ex.getMessage()); 334 return null; 335 } 336 337 return obj; 338 } 339 340 private void addMoreOptions() 341 { 342 moreButton.setText(" Less "); 343 344 creationOrderComposite = new Composite(moreOptionsComposite, SWT.BORDER); 345 creationOrderComposite.setLayout(new GridLayout(4, true)); 346 creationOrderComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); 347 348 creationOrderHelpButton = new Button(creationOrderComposite, SWT.PUSH); 349 creationOrderHelpButton.setImage(ViewProperties.getHelpIcon()); 350 creationOrderHelpButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); 351 creationOrderHelpButton.setToolTipText("Help on Creation Order"); 352 creationOrderHelpButton.addSelectionListener(new SelectionAdapter() { 353 @Override 354 public void widgetSelected(SelectionEvent e) 355 { 356 final String msg = 357 "Use Creation Order allows the user to set the creation order \n" 358 + "of links in a group, so that tracking, indexing, and iterating over links\n" 359 + "in groups can be possible. \n\n" 360 + "If the order flag Tracked is selected, links in a group can now \n" 361 + "be explicitly tracked by the order that they were created. \n\n" 362 + "If the order flag Tracked+Indexed is selected, links in a group can \n" 363 + "now be explicitly tracked and indexed in the order that they were created. \n\n" 364 + 365 "The default order in which links in a group are listed is alphanumeric-by-name. \n\n\n"; 366 367 Tools.showInformation(shell, "Create", msg); 368 } 369 }); 370 371 useCreationOrder = new Button(creationOrderComposite, SWT.CHECK); 372 useCreationOrder.setFont(curFont); 373 useCreationOrder.setText("Use Creation Order"); 374 useCreationOrder.addSelectionListener(new SelectionAdapter() { 375 @Override 376 public void widgetSelected(SelectionEvent e) 377 { 378 boolean isOrder = useCreationOrder.getSelection(); 379 380 if (isOrder) 381 orderFlags.setEnabled(true); 382 else 383 orderFlags.setEnabled(false); 384 } 385 }); 386 387 Label label = new Label(creationOrderComposite, SWT.RIGHT); 388 label.setFont(curFont); 389 label.setText("Order Flags: "); 390 label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false)); 391 392 orderFlags = new Combo(creationOrderComposite, SWT.DROP_DOWN | SWT.READ_ONLY); 393 orderFlags.setFont(curFont); 394 orderFlags.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true)); 395 orderFlags.add("Tracked"); 396 orderFlags.add("Tracked+Indexed"); 397 orderFlags.select(orderFlags.indexOf("Tracked")); 398 orderFlags.setEnabled(false); 399 400 storageTypeComposite = new Composite(moreOptionsComposite, SWT.BORDER); 401 storageTypeComposite.setLayout(new GridLayout(3, true)); 402 storageTypeComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); 403 404 storageTypeHelpButton = new Button(storageTypeComposite, SWT.PUSH); 405 storageTypeHelpButton.setImage(ViewProperties.getHelpIcon()); 406 storageTypeHelpButton.setToolTipText("Help on set Link Storage"); 407 storageTypeHelpButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); 408 storageTypeHelpButton.addSelectionListener(new SelectionAdapter() { 409 @Override 410 public void widgetSelected(SelectionEvent e) 411 { 412 final String msg = 413 "Set Link Storage allows the users to explicitly set the storage \n" 414 + "type of a group to be Compact or Indexed. \n\n" 415 + "Compact Storage: For groups with only a few links, compact link storage\n" 416 + "allows groups containing only a few links to take up much less space \n" 417 + "in the file. \n\n" 418 + "Indexed Storage: For groups with large number of links, indexed link storage \n" 419 + "provides a faster and more scalable method for storing and working with \n" 420 + "large groups containing many links. \n\n" 421 + "The threshold for switching between the compact and indexed storage \n" 422 + "formats is either set to default values or can be set by the user. \n\n" 423 + "<html><b>Max Compact</b></html> \n" 424 + "Max Compact is the maximum number of links to store in the group in a \n" 425 + "compact format, before converting the group to the Indexed format. Groups \n" 426 + "that are in compact format and in which the number of links rises above \n" 427 + " this threshold are automatically converted to indexed format. \n\n" 428 + "<html><b>Min Indexed</b></html> \n" 429 + "Min Indexed is the minimum number of links to store in the Indexed format. \n" 430 + "Groups which are in indexed format and in which the number of links falls \n" 431 + "below this threshold are automatically converted to compact format. \n\n\n"; 432 433 Tools.showInformation(shell, "Create", msg); 434 } 435 }); 436 437 setLinkStorage = new Button(storageTypeComposite, SWT.CHECK); 438 setLinkStorage.setFont(curFont); 439 setLinkStorage.setText("Set Link Storage"); 440 setLinkStorage.addSelectionListener(new SelectionAdapter() { 441 @Override 442 public void widgetSelected(SelectionEvent e) 443 { 444 if (setLinkStorage.getSelection()) { 445 compactField.setEnabled(true); 446 indexedField.setEnabled(true); 447 } 448 else { 449 compactField.setText("8"); 450 compactField.setEnabled(false); 451 indexedField.setText("6"); 452 indexedField.setEnabled(false); 453 } 454 } 455 }); 456 457 Composite indexedComposite = new Composite(storageTypeComposite, SWT.NONE); 458 indexedComposite.setLayout(new GridLayout(2, true)); 459 indexedComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true)); 460 461 Label minLabel = new Label(indexedComposite, SWT.LEFT); 462 minLabel.setFont(curFont); 463 minLabel.setText("Min Indexed: "); 464 465 Label maxLabel = new Label(indexedComposite, SWT.LEFT); 466 maxLabel.setFont(curFont); 467 maxLabel.setText("Max Compact: "); 468 469 indexedField = new Text(indexedComposite, SWT.SINGLE | SWT.BORDER); 470 indexedField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); 471 indexedField.setFont(curFont); 472 indexedField.setText("6"); 473 indexedField.setTextLimit(5); 474 indexedField.setEnabled(false); 475 indexedField.addVerifyListener(new VerifyListener() { 476 @Override 477 public void verifyText(VerifyEvent e) 478 { 479 String input = e.text; 480 481 char[] chars = new char[input.length()]; 482 input.getChars(0, chars.length, chars, 0); 483 for (int i = 0; i < chars.length; i++) { 484 if (!('0' <= chars[i] && chars[i] <= '9')) { 485 e.doit = false; 486 return; 487 } 488 } 489 } 490 }); 491 492 compactField = new Text(indexedComposite, SWT.SINGLE | SWT.BORDER); 493 compactField.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); 494 compactField.setFont(curFont); 495 compactField.setText("8"); 496 compactField.setTextLimit(5); 497 compactField.setEnabled(false); 498 compactField.addVerifyListener(new VerifyListener() { 499 @Override 500 public void verifyText(VerifyEvent e) 501 { 502 String input = e.text; 503 504 char[] chars = new char[input.length()]; 505 input.getChars(0, chars.length, chars, 0); 506 for (int i = 0; i < chars.length; i++) { 507 if (!('0' <= chars[i] && chars[i] <= '9')) { 508 e.doit = false; 509 return; 510 } 511 } 512 } 513 }); 514 515 shell.pack(); 516 517 shell.setMinimumSize(shell.computeSize(SWT.DEFAULT, SWT.DEFAULT)); 518 519 Rectangle parentBounds = shell.getParent().getBounds(); 520 Point shellSize = shell.getSize(); 521 shell.setLocation((parentBounds.x + (parentBounds.width / 2)) - (shellSize.x / 2), 522 (parentBounds.y + (parentBounds.height / 2)) - (shellSize.y / 2)); 523 } 524 525 private void removeMoreOptions() 526 { 527 moreButton.setText(" More "); 528 529 creationOrderHelpButton.dispose(); 530 storageTypeHelpButton.dispose(); 531 532 creationOrderComposite.dispose(); 533 storageTypeComposite.dispose(); 534 535 shell.layout(true, true); 536 shell.pack(); 537 538 shell.setMinimumSize(originalSize); 539 shell.setSize(originalSize); 540 541 Rectangle parentBounds = shell.getParent().getBounds(); 542 Point shellSize = shell.getSize(); 543 shell.setLocation((parentBounds.x + (parentBounds.width / 2)) - (shellSize.x / 2), 544 (parentBounds.y + (parentBounds.height / 2)) - (shellSize.y / 2)); 545 } 546}