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.lang.reflect.Array; 018 019import org.eclipse.swt.SWT; 020import org.eclipse.swt.events.DisposeEvent; 021import org.eclipse.swt.events.DisposeListener; 022import org.eclipse.swt.events.SelectionAdapter; 023import org.eclipse.swt.events.SelectionEvent; 024import org.eclipse.swt.graphics.Font; 025import org.eclipse.swt.graphics.Point; 026import org.eclipse.swt.graphics.Rectangle; 027import org.eclipse.swt.layout.GridData; 028import org.eclipse.swt.layout.GridLayout; 029import org.eclipse.swt.widgets.Button; 030import org.eclipse.swt.widgets.Composite; 031import org.eclipse.swt.widgets.Dialog; 032import org.eclipse.swt.widgets.Display; 033import org.eclipse.swt.widgets.Label; 034import org.eclipse.swt.widgets.List; 035import org.eclipse.swt.widgets.Shell; 036import org.eclipse.swt.widgets.Text; 037 038import hdf.view.Tools; 039import hdf.view.ViewProperties; 040 041/** 042 * MathConversionDialog shows a message dialog requesting user input for math 043 * conversion. 044 * 045 * @author Jordan T. Henderson 046 * @version 2.4 1/28/2016 047 */ 048public class MathConversionDialog extends Dialog { 049 private Shell shell; 050 051 private Font curFont; 052 053 private Text aField; 054 055 private Text bField; 056 057 private Text infoArea; 058 059 private List functionList; 060 061 private Object dataValue; 062 063 private char NT; 064 065 private String[] functionDescription; 066 067 private boolean isConverted; 068 069 /** 070 * Constructs MathConversionDialog. 071 * 072 * @param parent 073 * the owner of the input 074 * @param data 075 * the data array to convert. 076 */ 077 public MathConversionDialog(Shell parent, Object data) { 078 super(parent, SWT.APPLICATION_MODAL); 079 080 try { 081 curFont = new Font( 082 Display.getCurrent(), 083 ViewProperties.getFontType(), 084 ViewProperties.getFontSize(), 085 SWT.NORMAL); 086 } 087 catch (Exception ex) { 088 curFont = null; 089 } 090 091 isConverted = false; 092 dataValue = data; 093 NT = ' '; 094 095 String cName = data.getClass().getName(); 096 int cIndex = cName.lastIndexOf('['); 097 if (cIndex >= 0) { 098 NT = cName.charAt(cIndex + 1); 099 } 100 101 String[] tmpStrs = { 102 "The filter by lower and upper bounds. x=a if x<a; x=b if x>b." 103 + "\ne.g.\n x=5, [0, 127]=5\n x=-5, [0, 127]=0\n x=255, [0, 127]=127.", 104 "The absolute value of a number, the number without its sign." 105 + "\ne.g.\n abs(5)=5\n abs(-5)=5.", 106 "Linear function." + "\ne.g.\n a=5, b=2, x=2.5, a+b*x=10.", 107 "The result of a number raised to power of a." 108 + "\ne.g.\n x=2.5, a=10, pow(x, a)=9536.743\n x=25, a=0.5, pow(x, a)=5.", 109 "The exponential number e (i.e., 2.718...) raised to the power of x." 110 + "\ne.g.\n exp(5.0)=148.41316\n exp(5.5)=244.69193", 111 "The natural logarithm (base e) of x." 112 + "\ne.g.\n ln(20.085541)=3\n ln(10)=2.302585", 113 "The logarithm of x to the base of a, \"a\" must be an integer > 0." 114 + "\ne.g.\n log(10, 2)=3.321928\n log(2, 10)=0.30103", 115 "The trigonometric sine of angle x in radians." 116 + "\ne.g.\n sin(0.523599)=0.5\n sin(1.047198)=0.866025", 117 "The trigonometric cosine of angle x in radians." 118 + "\ne.g.\n cos(0.523599)=0.866025\n cos(1.047198)=0.5", 119 "The trigonometric tangent of angle x in radians." 120 + "\ne.g.\n tan(0.785398)=1\n tan(1.047198)=1.732051" }; 121 122 functionDescription = tmpStrs; 123 } 124 125 /** 126 * Open the MathConversionDialog for converting data. 127 */ 128 public void open() { 129 Shell parent = getParent(); 130 shell = new Shell(parent, SWT.SHELL_TRIM | SWT.APPLICATION_MODAL); 131 shell.setFont(curFont); 132 shell.setText("Convert Data..."); 133 shell.setImage(ViewProperties.getHdfIcon()); 134 shell.setLayout(new GridLayout(1, true)); 135 136 // Create content region 137 org.eclipse.swt.widgets.Group contentGroup = new org.eclipse.swt.widgets.Group(shell, SWT.NONE); 138 contentGroup.setFont(curFont); 139 contentGroup.setText("Converting Data With A Mathematic Function"); 140 contentGroup.setLayout(new GridLayout(2, false)); 141 contentGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); 142 143 String[] functionNames = { "[a, b]", "abs (x)", "a + b * x", 144 "pow (x, a)", "exp (x)", "ln (x)", "log (a, x)", "sin (x)", 145 "cos (x)", "tan (x)" }; 146 147 functionList = new List(contentGroup, SWT.SINGLE | SWT.BORDER); 148 functionList.setFont(curFont); 149 functionList.setItems(functionNames); 150 GridData functionListData = new GridData(SWT.FILL, SWT.FILL, true, false); 151 functionListData.minimumWidth = 350; 152 functionList.setLayoutData(functionListData); 153 functionList.addSelectionListener(new SelectionAdapter() { 154 @Override 155 public void widgetSelected(SelectionEvent e) { 156 int index = functionList.getSelectionIndex(); 157 infoArea.setText(functionDescription[index]); 158 159 if ((index == 0) || (index == 2)) { 160 aField.setEnabled(true); 161 bField.setEnabled(true); 162 } 163 else if ((index == 3) || (index == 6)) { 164 aField.setEnabled(true); 165 bField.setEnabled(false); 166 } 167 else { 168 aField.setEnabled(false); 169 bField.setEnabled(false); 170 } 171 } 172 }); 173 174 Composite fieldComposite = new Composite(contentGroup, SWT.NONE); 175 fieldComposite.setLayout(new GridLayout(2, false)); 176 fieldComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 177 178 Label label = new Label(fieldComposite, SWT.RIGHT); 179 label.setFont(curFont); 180 label.setText("a = "); 181 182 aField = new Text(fieldComposite, SWT.SINGLE | SWT.BORDER); 183 GridData aFieldData = new GridData(SWT.FILL, SWT.FILL, true, false); 184 aFieldData.minimumWidth = 100; 185 aField.setLayoutData(aFieldData); 186 aField.setFont(curFont); 187 aField.setText("0"); 188 aField.setEnabled(false); 189 190 label = new Label(fieldComposite, SWT.RIGHT); 191 label.setFont(curFont); 192 label.setText("b = "); 193 194 bField = new Text(fieldComposite, SWT.SINGLE | SWT.BORDER); 195 bField.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); 196 bField.setFont(curFont); 197 bField.setText("1"); 198 bField.setEnabled(false); 199 200 infoArea = new Text(contentGroup, SWT.MULTI | SWT.BORDER | SWT.WRAP); 201 infoArea.setEditable(false); 202 infoArea.setFont(curFont); 203 infoArea.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_GRAY)); 204 GridData infoAreaData = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1); 205 infoAreaData.minimumHeight = 150; 206 infoArea.setLayoutData(infoAreaData); 207 208 // Create Ok/Cancel button region 209 Composite buttonComposite = new Composite(shell, SWT.NONE); 210 buttonComposite.setLayout(new GridLayout(2, true)); 211 buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1)); 212 213 Button okButton = new Button(buttonComposite, SWT.PUSH); 214 okButton.setFont(curFont); 215 okButton.setText(" &OK "); 216 okButton.setLayoutData(new GridData(SWT.END, SWT.FILL, true, false)); 217 okButton.addSelectionListener(new SelectionAdapter() { 218 @Override 219 public void widgetSelected(SelectionEvent e) { 220 isConverted = convertData(); 221 222 shell.dispose(); 223 } 224 }); 225 226 Button cancelButton = new Button(buttonComposite, SWT.PUSH); 227 cancelButton.setFont(curFont); 228 cancelButton.setText(" &Cancel "); 229 cancelButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, true, false)); 230 cancelButton.addSelectionListener(new SelectionAdapter() { 231 @Override 232 public void widgetSelected(SelectionEvent e) { 233 isConverted = false; 234 235 shell.dispose(); 236 } 237 }); 238 239 shell.pack(); 240 241 shell.addDisposeListener(new DisposeListener() { 242 @Override 243 public void widgetDisposed(DisposeEvent e) { 244 if (curFont != null) curFont.dispose(); 245 } 246 }); 247 248 shell.setMinimumSize(shell.computeSize(SWT.DEFAULT, SWT.DEFAULT)); 249 250 Rectangle parentBounds = parent.getBounds(); 251 Point shellSize = shell.getSize(); 252 shell.setLocation((parentBounds.x + (parentBounds.width / 2)) - (shellSize.x / 2), 253 (parentBounds.y + (parentBounds.height / 2)) - (shellSize.y / 2)); 254 255 shell.open(); 256 257 Display display = parent.getDisplay(); 258 while(!shell.isDisposed()) { 259 if (!display.readAndDispatch()) 260 display.sleep(); 261 } 262 } 263 264 private boolean convertData() { 265 double a = 0, b = 1; 266 267 int index = functionList.getSelectionIndex(); 268 269 try { 270 if ((index == 0) || (index == 2)) { 271 a = Double.parseDouble(aField.getText().trim()); 272 b = Double.parseDouble(bField.getText().trim()); 273 } 274 else if (index == 3) { 275 a = Double.parseDouble(aField.getText().trim()); 276 } 277 else if (index == 6) { 278 a = Integer.parseInt(aField.getText().trim()); 279 if (a <= 0) { 280 shell.getDisplay().beep(); 281 Tools.showError(shell, "Convert", "a must be an integer greater than zero."); 282 return false; 283 } 284 } 285 } 286 catch (Exception ex) { 287 shell.getDisplay().beep(); 288 Tools.showError(shell, "Convert", ex.getMessage()); 289 return false; 290 } 291 292 int n = Array.getLength(dataValue); 293 double value = 0, x = 0; 294 295 switch (NT) { 296 case 'B': 297 byte[] bdata = (byte[]) dataValue; 298 for (int i = 0; i < n; i++) { 299 x = bdata[i]; 300 value = y(index, x, a, b); 301 if ((value > Byte.MAX_VALUE) || (value < Byte.MIN_VALUE)) { 302 Tools.showError(shell, "Convert", "Invalid byte value: " + (long) value); 303 return false; 304 } 305 306 bdata[i] = (byte) value; 307 } 308 break; 309 case 'S': 310 short[] sdata = (short[]) dataValue; 311 for (int i = 0; i < n; i++) { 312 x = sdata[i]; 313 value = y(index, x, a, b); 314 if ((value > Short.MAX_VALUE) || (value < Short.MIN_VALUE)) { 315 Tools.showError(shell, "Convert", "Invalid short value: " + (long) value); 316 return false; 317 } 318 319 sdata[i] = (short) value; 320 } 321 break; 322 case 'I': 323 int[] idata = (int[]) dataValue; 324 for (int i = 0; i < n; i++) { 325 x = idata[i]; 326 value = y(index, x, a, b); 327 if ((value > Integer.MAX_VALUE) || (value < Integer.MIN_VALUE)) { 328 Tools.showError(shell, "Convert", "Invalid int value: " + (long) value); 329 return false; 330 } 331 332 idata[i] = (int) value; 333 } 334 break; 335 case 'J': 336 long[] ldata = (long[]) dataValue; 337 for (int i = 0; i < n; i++) { 338 x = ldata[i]; 339 value = y(index, x, a, b); 340 if ((value > Long.MAX_VALUE) || (value < Long.MIN_VALUE)) { 341 Tools.showError(shell, "Convert", "Invalid long value: " + (long) value); 342 return false; 343 } 344 345 ldata[i] = (long) value; 346 } 347 break; 348 case 'F': 349 float[] fdata = (float[]) dataValue; 350 for (int i = 0; i < n; i++) { 351 x = fdata[i]; 352 value = y(index, x, a, b); 353 if ((value > Float.MAX_VALUE) || (value < -Float.MAX_VALUE) 354 || (value == Float.NaN)) { 355 Tools.showError(shell, "Convert", "Invalid float value: " + value); 356 return false; 357 } 358 359 fdata[i] = (float) value; 360 } 361 break; 362 case 'D': 363 double[] ddata = (double[]) dataValue; 364 for (int i = 0; i < n; i++) { 365 x = ddata[i]; 366 value = y(index, x, a, b); 367 if ((value > Double.MAX_VALUE) || (value < -Double.MAX_VALUE) 368 || (value == Double.NaN)) { 369 Tools.showError(shell, "Convert", "Invalid double value: " + value); 370 return false; 371 } 372 373 ddata[i] = value; 374 } 375 break; 376 default: 377 break; 378 } 379 380 return true; 381 } 382 383 private double y(int index, double x, double a, double b) { 384 double y = x; 385 386 switch (index) { 387 case 0: 388 if (x < a) { 389 y = a; 390 } 391 else if (x > b) { 392 y = b; 393 } 394 break; 395 case 1: 396 y = Math.abs(x); 397 break; 398 case 2: 399 y = (a + b * x); 400 break; 401 case 3: 402 y = Math.pow(x, a); 403 break; 404 case 4: 405 y = Math.exp(x); 406 break; 407 case 5: 408 y = Math.log(x); 409 break; 410 case 6: 411 y = (Math.log(x) / Math.log(a)); 412 break; 413 case 7: 414 y = Math.sin(x); 415 break; 416 case 8: 417 y = Math.cos(x); 418 break; 419 case 9: 420 y = Math.tan(x); 421 break; 422 default: 423 break; 424 } 425 426 return y; 427 } 428 429 /** @return true if the data is successfully converted. */ 430 public boolean isConverted() { 431 return isConverted; 432 } 433}