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 http://hdfgroup.org/products/hdf-java/doc/Copyright.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; 016 017import java.awt.BorderLayout; 018import java.awt.Dimension; 019import java.awt.GridLayout; 020import java.awt.Point; 021import java.awt.Toolkit; 022import java.awt.event.ActionEvent; 023import java.awt.event.ActionListener; 024import java.awt.event.KeyEvent; 025import java.lang.reflect.Array; 026 027import javax.swing.BorderFactory; 028import javax.swing.JButton; 029import javax.swing.JDialog; 030import javax.swing.JFrame; 031import javax.swing.JLabel; 032import javax.swing.JList; 033import javax.swing.JOptionPane; 034import javax.swing.JPanel; 035import javax.swing.JScrollPane; 036import javax.swing.JTextArea; 037import javax.swing.JTextField; 038import javax.swing.ListSelectionModel; 039import javax.swing.border.TitledBorder; 040import javax.swing.event.ListSelectionEvent; 041import javax.swing.event.ListSelectionListener; 042 043/** 044 * MathConversionDialog shows a message dialog requesting user input for math 045 * conversion. 046 * 047 * @author Peter X. Cao 048 * @version 2.4 9/6/2007 049 */ 050public class MathConversionDialog extends JDialog implements ActionListener, 051 ListSelectionListener { 052 private static final long serialVersionUID = 5136554941147830371L; 053 054 private JTextField aField, bField; 055 056 private JTextArea infoArea; 057 058 private JList functionList; 059 060 private Object dataValue; 061 062 private char NT; 063 064 private final Toolkit toolkit; 065 066 private String[] functionDescription; 067 068 private boolean isConverted; 069 070 /** 071 * Constructs MathConversionDialog. 072 * 073 * @param owner 074 * the owner of the input 075 * @param data 076 * the data array to convert. 077 */ 078 public MathConversionDialog(JFrame owner, Object data) { 079 super(owner, "Convert Data...", true); 080 081 toolkit = Toolkit.getDefaultToolkit(); 082 isConverted = false; 083 dataValue = data; 084 NT = ' '; 085 086 String cName = data.getClass().getName(); 087 int cIndex = cName.lastIndexOf("["); 088 if (cIndex >= 0) { 089 NT = cName.charAt(cIndex + 1); 090 } 091 092 String[] functionNames = { "[a, b]", "abs (x)", "a + b * x", 093 "pow (x, a)", "exp (x)", "ln (x)", "log (a, x)", "sin (x)", 094 "cos (x)", "tan (x)" }; 095 functionList = new JList(functionNames); 096 functionList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 097 functionList.addListSelectionListener(this); 098 099 String[] tmpStrs = { 100 "The filter by lower and upper bounds. x=a if x<a; x=b if x>b." 101 + "\ne.g.\n x=5, [0, 127]=5\n x=-5, [0, 127]=0\n x=255, [0, 127]=127.", 102 "The absolute value of a number, the number without its sign." 103 + "\ne.g.\n abs(5)=5\n abs(-5)=5.", 104 "Linear function." + "\ne.g.\n a=5, b=2, x=2.5, a+b*x=10.", 105 "The result of a number raised to power of a." 106 + "\ne.g.\n x=2.5, a=10, pow(x, a)=9536.743\n x=25, a=0.5, pow(x, a)=5.", 107 "The exponential number e (i.e., 2.718...) raised to the power of x." 108 + "\ne.g.\n exp(5.0)=148.41316\n exp(5.5)=244.69193", 109 "The natural logarithm (base e) of x." 110 + "\ne.g.\n ln(20.085541)=3\n ln(10)=2.302585", 111 "The logarithm of x to the base of a, \"a\" must be an integer > 0." 112 + "\ne.g.\n log(10, 2)=3.321928\n log(2, 10)=0.30103", 113 "The trigonometric sine of angle x in radians." 114 + "\ne.g.\n sin(0.523599)=0.5\n sin(1.047198)=0.866025", 115 "The trigonometric cosine of angle x in radians." 116 + "\ne.g.\n cos(0.523599)=0.866025\n cos(1.047198)=0.5", 117 "The trigonometric tangent of angle x in radians." 118 + "\ne.g.\n tan(0.785398)=1\n tan(1.047198)=1.732051" }; 119 120 functionDescription = tmpStrs; 121 122 JPanel contentPane = (JPanel) getContentPane(); 123 contentPane.setLayout(new BorderLayout(5, 5)); 124 contentPane.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 5)); 125 int w = 500 + (ViewProperties.getFontSize() - 12) * 15; 126 int h = 300 + (ViewProperties.getFontSize() - 12) * 10; 127 contentPane.setPreferredSize(new Dimension(w, h)); 128 129 JButton okButton = new JButton(" Ok "); 130 okButton.setActionCommand("Ok"); 131 okButton.setMnemonic(KeyEvent.VK_O); 132 okButton.addActionListener(this); 133 134 JButton cancelButton = new JButton("Cancel"); 135 cancelButton.setMnemonic(KeyEvent.VK_C); 136 cancelButton.setActionCommand("Cancel"); 137 cancelButton.addActionListener(this); 138 139 // set OK and CANCEL buttons 140 JPanel buttonPanel = new JPanel(); 141 buttonPanel.add(okButton); 142 buttonPanel.add(cancelButton); 143 contentPane.add(buttonPanel, BorderLayout.SOUTH); 144 145 // set name, parent, width and height panel 146 JPanel centerP = new JPanel(); 147 centerP.setLayout(new BorderLayout(10, 10)); 148 JScrollPane scroller = new JScrollPane(functionList); 149 centerP.add(scroller, BorderLayout.CENTER); 150 151 JPanel tmpP = new JPanel(); 152 tmpP.setLayout(new BorderLayout(5, 5)); 153 154 JPanel tmpP0 = new JPanel(); 155 tmpP0.setLayout(new GridLayout(4, 1, 5, 5)); 156 tmpP0.add(new JLabel("a = ")); 157 tmpP0.add(new JLabel("b = ")); 158 tmpP0.add(new JLabel(" ")); 159 tmpP0.add(new JLabel(" ")); 160 tmpP.add(tmpP0, BorderLayout.WEST); 161 162 tmpP0 = new JPanel(); 163 tmpP0.setLayout(new GridLayout(4, 1, 5, 5)); 164 tmpP0.add(aField = new JTextField("0")); 165 tmpP0.add(bField = new JTextField("1")); 166 tmpP0.add(new JLabel(" ")); 167 tmpP0.add(new JLabel(" ")); 168 tmpP.add(tmpP0, BorderLayout.CENTER); 169 170 centerP.add(tmpP, BorderLayout.EAST); 171 172 tmpP0 = new JPanel(); 173 tmpP0.setLayout(new BorderLayout()); 174 tmpP0.add(infoArea = new JTextArea(4, 80), BorderLayout.CENTER); 175 infoArea.setEditable(false); 176 infoArea.setLineWrap(true); 177 infoArea.setBackground(java.awt.Color.lightGray); 178 infoArea.setWrapStyleWord(true); 179 180 centerP.setBorder(new TitledBorder( 181 "Converting Data With A Mathematic Function")); 182 centerP.add(tmpP0, BorderLayout.SOUTH); 183 aField.setEnabled(false); 184 bField.setEnabled(false); 185 186 contentPane.add(centerP, BorderLayout.CENTER); 187 188 // locate the H5Property dialog 189 Point l = owner.getLocation(); 190 l.x += 250; 191 l.y += 80; 192 setLocation(l); 193 validate(); 194 pack(); 195 } 196 197 private boolean convertData() { 198 double a = 0, b = 1; 199 200 int index = functionList.getSelectedIndex(); 201 try { 202 if ((index == 0) || (index == 2)) { 203 a = Double.parseDouble(aField.getText().trim()); 204 b = Double.parseDouble(bField.getText().trim()); 205 } 206 else if (index == 3) { 207 a = Double.parseDouble(aField.getText().trim()); 208 } 209 else if (index == 6) { 210 a = Integer.parseInt(aField.getText().trim()); 211 if (a <= 0) { 212 toolkit.beep(); 213 JOptionPane.showMessageDialog(this, 214 "a must be an integer greater than zero.", 215 getTitle(), JOptionPane.ERROR_MESSAGE); 216 return false; 217 } 218 } 219 } 220 catch (Exception ex) { 221 toolkit.beep(); 222 JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), 223 JOptionPane.ERROR_MESSAGE); 224 return false; 225 } 226 227 int n = Array.getLength(dataValue); 228 double value = 0, x = 0; 229 230 switch (NT) { 231 case 'B': 232 byte[] bdata = (byte[]) dataValue; 233 for (int i = 0; i < n; i++) { 234 x = bdata[i]; 235 value = y(index, x, a, b); 236 if ((value > Byte.MAX_VALUE) || (value < Byte.MIN_VALUE)) { 237 JOptionPane.showMessageDialog(this, "Invalid byte value: " 238 + (long) value, getTitle(), 239 JOptionPane.ERROR_MESSAGE); 240 return false; 241 } 242 243 bdata[i] = (byte) value; 244 } // for (int i=0; i<n; i++) 245 break; 246 case 'S': 247 short[] sdata = (short[]) dataValue; 248 for (int i = 0; i < n; i++) { 249 x = sdata[i]; 250 value = y(index, x, a, b); 251 if ((value > Short.MAX_VALUE) || (value < Short.MIN_VALUE)) { 252 JOptionPane.showMessageDialog(this, "Invalid short value: " 253 + (long) value, getTitle(), 254 JOptionPane.ERROR_MESSAGE); 255 return false; 256 } 257 258 sdata[i] = (short) value; 259 } // for (int i=0; i<n; i++) 260 break; 261 case 'I': 262 int[] idata = (int[]) dataValue; 263 for (int i = 0; i < n; i++) { 264 x = idata[i]; 265 value = y(index, x, a, b); 266 if ((value > Integer.MAX_VALUE) || (value < Integer.MIN_VALUE)) { 267 JOptionPane.showMessageDialog(this, "Invalid int value: " 268 + (long) value, getTitle(), 269 JOptionPane.ERROR_MESSAGE); 270 return false; 271 } 272 273 idata[i] = (int) value; 274 } // for (int i=0; i<n; i++) 275 break; 276 case 'J': 277 long[] ldata = (long[]) dataValue; 278 for (int i = 0; i < n; i++) { 279 x = ldata[i]; 280 value = y(index, x, a, b); 281 if ((value > Long.MAX_VALUE) || (value < Long.MIN_VALUE)) { 282 JOptionPane.showMessageDialog(this, "Invalid long value: " 283 + (long) value, getTitle(), 284 JOptionPane.ERROR_MESSAGE); 285 return false; 286 } 287 288 ldata[i] = (long) value; 289 } // for (int i=0; i<n; i++) 290 break; 291 case 'F': 292 float[] fdata = (float[]) dataValue; 293 for (int i = 0; i < n; i++) { 294 x = fdata[i]; 295 value = y(index, x, a, b); 296 if ((value > Float.MAX_VALUE) || (value < -Float.MAX_VALUE) 297 || (value == Float.NaN)) { 298 JOptionPane.showMessageDialog(this, "Invalid float value: " 299 + value, getTitle(), JOptionPane.ERROR_MESSAGE); 300 return false; 301 } 302 303 fdata[i] = (float) value; 304 } // for (int i=0; i<n; i++) 305 break; 306 case 'D': 307 double[] ddata = (double[]) dataValue; 308 for (int i = 0; i < n; i++) { 309 x = ddata[i]; 310 value = y(index, x, a, b); 311 if ((value > Double.MAX_VALUE) || (value < -Double.MAX_VALUE) 312 || (value == Double.NaN)) { 313 JOptionPane.showMessageDialog(this, 314 "Invalid double value: " + value, getTitle(), 315 JOptionPane.ERROR_MESSAGE); 316 return false; 317 } 318 319 ddata[i] = value; 320 } // for (int i=0; i<n; i++) 321 break; 322 default: 323 break; 324 } 325 326 return true; 327 } 328 329 public void actionPerformed(ActionEvent e) { 330 Object source = e.getSource(); 331 String cmd = e.getActionCommand(); 332 333 if (cmd.equals("Ok")) { 334 isConverted = convertData(); 335 // if (isConverted) 336 dispose(); 337 } 338 if (cmd.equals("Cancel")) { 339 isConverted = false; 340 dispose(); 341 } 342 } 343 344 public void valueChanged(ListSelectionEvent e) { 345 if (e.getValueIsAdjusting()) { 346 return; 347 } 348 349 if (!e.getSource().equals(functionList)) { 350 return; 351 } 352 353 if (functionList.isSelectionEmpty()) { 354 return; 355 } 356 357 int index = functionList.getSelectedIndex(); 358 infoArea.setText(functionDescription[index]); 359 360 if ((index == 0) || (index == 2)) { 361 aField.setEnabled(true); 362 bField.setEnabled(true); 363 } 364 else if ((index == 3) || (index == 6)) { 365 aField.setEnabled(true); 366 bField.setEnabled(false); 367 } 368 else { 369 aField.setEnabled(false); 370 bField.setEnabled(false); 371 } 372 } 373 374 private double y(int index, double x, double a, double b) { 375 double y = x; 376 switch (index) { 377 case 0: 378 if (x < a) { 379 y = a; 380 } 381 else if (x > b) { 382 y = b; 383 } 384 break; 385 case 1: 386 y = Math.abs(x); 387 break; 388 case 2: 389 y = (a + b * x); 390 break; 391 case 3: 392 y = Math.pow(x, a); 393 break; 394 case 4: 395 y = Math.exp(x); 396 break; 397 case 5: 398 y = Math.log(x); 399 break; 400 case 6: 401 y = (Math.log(x) / Math.log(a)); 402 break; 403 case 7: 404 y = Math.sin(x); 405 break; 406 case 8: 407 y = Math.cos(x); 408 break; 409 case 9: 410 y = Math.tan(x); 411 break; 412 default: 413 y = x; 414 break; 415 } 416 417 return y; 418 } 419 420 /** 421 * Returns true if the data is successfully converted. 422 * 423 * @return true if the data is successfully converted; false otherwise 424 */ 425 public boolean isConverted() { 426 return isConverted; 427 } 428 429}