package com.drawbridge.utils; import java.awt.Component; import java.awt.event.ActionEvent; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.math.RoundingMode; import java.net.MalformedURLException; import java.text.DecimalFormat; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; import java.util.Properties; import javax.imageio.ImageIO; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.Clip; import javax.swing.AbstractAction; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import com.drawbridge.Activity; import com.drawbridge.Main; import com.drawbridge.dm.DMImageFactory.DMImage; import com.drawbridge.text.TextPanel; import com.drawbridge.vl.VLPanel; import com.google.caja.util.Pair; public class Utils { public static boolean DEBUG = true; public static class out { public static void println(Class<?> callingClass, String string) { if (Utils.DEBUG == true) { System.out.println(String.format("%-40s %s", callingClass.getSimpleName(), string)); } } public static void println(Object obj) { if (Utils.DEBUG == true) { System.out.println(obj.toString()); } } } public static class err { public static void println(Class<?> callingClass, String string) { if (Utils.DEBUG == true) { System.err.println(String.format("%-40s %s", callingClass.getSimpleName(), string)); } } public static void println(Object obj) { if (Utils.DEBUG == true) { System.err.println(obj.toString()); } } } public static void playClick() { new Thread(new Runnable() { @Override public void run() { Clip clip; try { InputStream is = Activity.class.getResourceAsStream("/Assets/click.wav"); clip = AudioSystem.getClip(); AudioInputStream inputStream = AudioSystem.getAudioInputStream(is); clip.open(inputStream); clip.start(); is.close(); } catch (Exception e) { e.printStackTrace(); } } }).start(); } public static void adaptTextFieldInputForVariableNames(final JTextField textField, final char replacementChar) { KeyStroke keyStroke = KeyStroke.getKeyStroke(Character.valueOf(' '), 0); textField.getInputMap(JComponent.WHEN_FOCUSED).put(keyStroke, new AbstractAction() { private static final long serialVersionUID = -7485963765323890085L; public void actionPerformed(ActionEvent e) { int pos = textField.getCaretPosition(); String o = textField.getText(); String n = o.substring(0, pos); n += replacementChar; n += o.substring(pos, o.length()); textField.setText(n); } }); } public static boolean arrayContains(Object[] array, Object obj) { for (Object arrayElement : array) { if (arrayElement.equals(obj)) ; return true; } return false; } public static int limitToBounds(int source, int limitLo, int limitHi) { int result; if (source < limitLo) result = limitLo; else if (source > limitHi) result = limitHi; else result = source; return result; } public static String removeSegment(String snapshot, int s, int f) { s = limitToBounds(s, 0, snapshot.length()); f = limitToBounds(f, 0, snapshot.length()); String left = snapshot.substring(0, s); String right = snapshot.substring(f, snapshot.length()); return left + right; } public static int safeLongToInt(long l) { if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) { throw new IllegalArgumentException(l + " cannot be cast to int without changing its value."); } return (int) l; } public static boolean containsClassType(Collection<?> c, Class<?> t) { if (c != null && t != null) { Iterator<?> it = c.iterator(); if (it != null) { while (it.hasNext()) { if (it.next().getClass().equals(t)) return true; } } } return false; } public static boolean saveTextToFile(String text, File file) { try { if (!file.exists()) { file.getParentFile().mkdirs(); file.createNewFile(); } BufferedWriter output = new BufferedWriter(new FileWriter(file)); output.write(text); output.close(); return true; } catch (IOException e) { e.printStackTrace(); return false; } } public static Integer getNumberOfLinesFromPackagedFile(String name) { InputStream is = Activity.class.getResourceAsStream(name); int lineCount = 0; BufferedReader br = new BufferedReader(new InputStreamReader(is)); try { while (br.readLine() != null) { lineCount++; } br.close(); is.close(); } catch (IOException e) { e.printStackTrace(); } return lineCount; } public static String loadTextFromPackagedFile(String name) { String result = null; InputStream is = Activity.class.getResourceAsStream(name); StringBuilder sb = new StringBuilder(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); String line = null; try { while ((line = br.readLine()) != null) { sb.append(line); sb.append(System.getProperty("line.separator")); } br.close(); is.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } result = sb.toString(); return result; } public static boolean saveImageToFile(DMImage image, String prefix) { // Use the name as the unique identifier File imageFile = new File(Utils.getTemporaryFolder() + prefix + "/" + image.getName() + ".jpg"); if (imageFile.exists()) { // We'll override it imageFile.delete(); } imageFile.mkdirs(); boolean created = false; try { ImageIO.write(image.getImage(), "png", imageFile); created = true; } catch (IOException e) { created = false; Utils.out.println("Could not create file: " + imageFile.getAbsolutePath()); e.printStackTrace(); } if (created) { try { image.setFileURL(imageFile.toURI().toURL()); } catch (MalformedURLException e) { e.printStackTrace(); } return true; } return false; } public static void removeComponent(JPanel jp, Class<?> classToRemove) { Component[] components = jp.getComponents(); for (Component c : components) { if (c.getClass().equals(classToRemove)) { Utils.out.println(Utils.class, "REMOVED " + classToRemove.getSimpleName()); jp.remove(c); } } } /** * A basic synchronized scrolling listener. Doesn't actually enforce viewing actual lines, but assumes both segments * will have a similar number of lines. */ public static ChangeListener synchronizedScrollingListener = new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { if (TextPanel.hasInstance() && VLPanel.hasInstance() && TextPanel.getInstance().getScrollBar().getVerticalScrollBar().isShowing()) { JScrollBar vScrollText = TextPanel.getInstance().getScrollBar().getVerticalScrollBar(); JScrollBar vScrollVLJ = VLPanel.getInstance().getScrollBar().getVerticalScrollBar(); double test = vScrollVLJ.getMaximum() - vScrollVLJ.getVisibleAmount(); double test2 = vScrollText.getMaximum() - vScrollText.getVisibleAmount(); double ratio = (int) (test / test2); if (e.getSource().equals(VLPanel.getInstance().getScrollBar().getViewport())) { vScrollText.setValue((int) (vScrollVLJ.getValue() / ratio)); } else if (e.getSource().equals(TextPanel.getInstance().getScrollBar().getViewport())) { vScrollVLJ.setValue((int) (vScrollText.getValue() * ratio)); } } } }; public static Object loadDrawBridgeProperty(String key) { Properties properties = new Properties(); InputStream is = Main.class.getResourceAsStream("/db.properties"); if (is != null) { try { properties.load(is); } catch (IOException e) { e.printStackTrace(); } if (properties.containsKey(key)) { Object value = properties.get(key); Utils.out.println("Found mode properties for " + key + ":" + value); return value; } else { Utils.err.println("Found mode.properties file, but no " + key + " inside."); return null; } } else { Utils.err.println("Could not find mode.properties file."); return null; } } public static String getTemporaryFolder(){ return new JFileChooser().getFileSystemView().getDefaultDirectory().toString(); } public static LinkedList<Pair<Integer, Integer>> StringLCS(String oldString, String newString) { int M = oldString.length(); int N = newString.length(); LinkedList<Pair<Integer, Integer>> indices = new LinkedList<Pair<Integer, Integer>>(); boolean inNewText = false; int startOfNewText = 0; int[][] opt = new int[M + 1][N + 1]; for (int i = M - 1; i >= 0; i--) { for (int j = N - 1; j >= 0; j--) { if (oldString.substring(i, i+1).equals(newString.substring(j, j+1))) { opt[i][j] = opt[i + 1][j + 1] + 1; } else { opt[i][j] = Math.max(opt[i + 1][j], opt[i][j + 1]); } } } // recover LCS itself and print out non-matching lines int i = 0, j = 0; while (i < M && j < N) { if (oldString.substring(i, i+1).equals(newString.substring(j, j+1))) { // They are the same i++; j++; if(inNewText){ inNewText = false; Utils.out.println("Indices add 1"); indices.add(new Pair<Integer, Integer>(startOfNewText, j-1)); } } else if (opt[i + 1][j] >= opt[i][j + 1]) { i++; if(inNewText){ inNewText = false; Utils.out.println("Indices add 2"); indices.add(new Pair<Integer, Integer>(startOfNewText, j-1)); } // Utils.out.println("Remove1: " + oldString.substring(i-1, i)); } else { j++; Utils.out.println("Added1: " + newString.substring(j-1, j)); if(!inNewText){ inNewText = true; startOfNewText = j-1; } } } // dump out one remainder of one string if the other is exhausted while (i < M || j < N) { if (i == M) { j++; Utils.out.println("Added2: " + newString.substring(j-1, j)); if(!inNewText){ inNewText = true; startOfNewText = j-1; } } else if (j == N) { i++; if(inNewText){ inNewText = false; Utils.out.println("Indices add 3"); indices.add(new Pair<Integer, Integer>(startOfNewText, j-1)); } // Utils.out.println("Remove2: " + oldString.substring(i - 1, i)); } } if(inNewText){ inNewText = false; Utils.out.println("Added end case"); indices.add(new Pair<Integer, Integer>(startOfNewText, j)); } return indices; } public static Double toDecimalPlace(double raw, int decimalPlaces){ DecimalFormat df = new DecimalFormat(); df.setMaximumFractionDigits(decimalPlaces); df.setRoundingMode(RoundingMode.HALF_EVEN); String dp = df.format(raw); return Double.valueOf(dp); } }