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);
}
}