Switched to using nekohtml as html parser, externalized simmetrics (just copied the sourcefiles before), lots of buxfixes and improvements. Also started using an ant.
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<project name="FileBot" basedir="." default="fatjar">
|
||||
|
||||
<property name="title" value="${ant.project.name}" />
|
||||
<property name="version" value="2.1" />
|
||||
<property name="url" value="http://sourceforge.net/projects/filebot/" />
|
||||
|
||||
<property name="source" location="${basedir}/source" />
|
||||
<property name="build" location="${basedir}/build" />
|
||||
<property name="lib" location="${basedir}/lib" />
|
||||
|
||||
<property name="executable" location="${basedir}/${title}.jar" />
|
||||
|
||||
<property name="lib.nekohtml" value="nekohtml.jar" />
|
||||
<property name="lib.xerces" value="xercesImpl.jar" />
|
||||
<property name="lib.simmetrics" value="simmetrics_jar_v1_6_2_d07_02_07.jar" />
|
||||
|
||||
|
||||
<target name="jar" depends="build">
|
||||
<jar destfile="${executable}" duplicate="fail">
|
||||
<fileset dir="${build}" />
|
||||
|
||||
<manifest>
|
||||
<attribute name="Built-By" value="${user.name}" />
|
||||
<attribute name="Main-Class" value="Main" />
|
||||
<attribute name="Title" value="${title}" />
|
||||
<attribute name="Version" value="${version}" />
|
||||
<attribute name="URL" value="${url}" />
|
||||
</manifest>
|
||||
|
||||
<!-- include libs if fatjar is set -->
|
||||
<zipfileset src="${lib}/${lib.nekohtml}">
|
||||
<include if="fatjar" name="**/*.class" />
|
||||
<include if="fatjar" name="**/*.properties" />
|
||||
</zipfileset>
|
||||
<zipfileset src="${lib}/${lib.xerces}">
|
||||
<include if="fatjar" name="**/*.class" />
|
||||
</zipfileset>
|
||||
<zipfileset src="${lib}/${lib.simmetrics}">
|
||||
<include if="fatjar" name="**/*.class" />
|
||||
<exclude name="**/*Test*" />
|
||||
</zipfileset>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="fatjar">
|
||||
<antcall target="jar">
|
||||
<param name="fatjar" value="true" />
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="build" depends="clean">
|
||||
<!-- create build dir -->
|
||||
<mkdir dir="${build}" />
|
||||
|
||||
<!-- compile -->
|
||||
<javac srcdir="${source}" destdir="${build}">
|
||||
<classpath>
|
||||
<fileset dir="${lib}" includes="*.jar" />
|
||||
</classpath>
|
||||
</javac>
|
||||
|
||||
<!-- copy resources -->
|
||||
<copy todir="${build}">
|
||||
<fileset dir="${source}">
|
||||
<include name="**/*.png" />
|
||||
<include name="**/*.gif" />
|
||||
</fileset>
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
|
||||
<target name="clean">
|
||||
<delete dir="${build}" />
|
||||
<delete file="${executable}" verbose="true" />
|
||||
</target>
|
||||
|
||||
|
||||
<target name="run" depends="fatjar">
|
||||
<java jar="${executable}" fork="true" />
|
||||
</target>
|
||||
|
||||
</project>
|
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 117 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 31 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 24 KiB |
|
@ -0,0 +1,27 @@
|
|||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import net.sourceforge.filebot.ui.FileBotWindow;
|
||||
|
||||
|
||||
public class Main {
|
||||
|
||||
/**
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
|
||||
public void run() {
|
||||
new FileBotWindow().setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
|
||||
package net.sourceforge.filebot.resources;
|
||||
|
||||
|
||||
import java.awt.Image;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
|
||||
public class ResourceManager {
|
||||
|
||||
private static HashMap<String, URL> resourceMap = new HashMap<String, URL>();
|
||||
|
||||
static {
|
||||
putResource("window.icon.small", "window.icon.small.png");
|
||||
putResource("window.icon.big", "window.icon.big.png");
|
||||
|
||||
putResource("panel.analyze", "panel.analyze.png");
|
||||
putResource("panel.rename", "panel.rename.png");
|
||||
putResource("panel.create", "panel.create.png");
|
||||
putResource("panel.list", "panel.list.png");
|
||||
putResource("panel.search", "panel.search.png");
|
||||
|
||||
putResource("tree.open", "tree.open.png");
|
||||
putResource("tree.closed", "tree.closed.png");
|
||||
putResource("tree.leaf", "tree.leaf.png");
|
||||
|
||||
putResource("action.rename", "action.rename.png");
|
||||
putResource("action.down", "action.down.png");
|
||||
putResource("action.up", "action.up.png");
|
||||
putResource("action.save", "action.save.png");
|
||||
putResource("action.load", "action.load.png");
|
||||
putResource("action.clear", "action.clear.png");
|
||||
putResource("action.find", "action.find.png");
|
||||
|
||||
putResource("action.match.file2name", "action.match.file2name.png");
|
||||
putResource("action.match.name2file", "action.match.name2file.png");
|
||||
|
||||
putResource("message.info", "message.info.png");
|
||||
putResource("message.warning", "message.warning.png");
|
||||
|
||||
putResource("search.anidb", "search.anidb.png");
|
||||
putResource("search.tvdotcom", "search.tvdotcom.png");
|
||||
putResource("search.tvrage", "search.tvrage.png");
|
||||
|
||||
putResource("tab.close", "tab.close.png");
|
||||
putResource("tab.close.hover", "tab.close.hover.png");
|
||||
putResource("tab.loading", "tab.loading.gif");
|
||||
putResource("tab.history", "action.find.png");
|
||||
|
||||
putResource("loading", "loading.gif");
|
||||
|
||||
putResource("tree.expand", "tree.expand.png");
|
||||
putResource("tree.collapse", "tree.collapse.png");
|
||||
|
||||
putResource("panel.sfv", "panel.sfv.png");
|
||||
putResource("status.error", "status.error.png");
|
||||
putResource("status.ok", "status.ok.png");
|
||||
putResource("status.unknown", "status.unknown.png");
|
||||
putResource("status.warning", "status.warning.png");
|
||||
|
||||
putResource("decoration.header", "decoration.header.png");
|
||||
}
|
||||
|
||||
|
||||
private static void putResource(String name, String file) {
|
||||
resourceMap.put(name, ResourceManager.class.getResource(file));
|
||||
}
|
||||
|
||||
|
||||
public static Image getImage(String name) {
|
||||
if (!resourceMap.containsKey(name))
|
||||
return null;
|
||||
|
||||
try {
|
||||
return ImageIO.read(resourceMap.get(name));
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static ImageIcon getIcon(String name) {
|
||||
return new ImageIcon(resourceMap.get(name));
|
||||
}
|
||||
|
||||
}
|
After Width: | Height: | Size: 806 B |
After Width: | Height: | Size: 572 B |
After Width: | Height: | Size: 875 B |
After Width: | Height: | Size: 629 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 758 B |
After Width: | Height: | Size: 564 B |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 1002 B |
After Width: | Height: | Size: 722 B |
After Width: | Height: | Size: 1012 B |
After Width: | Height: | Size: 735 B |
After Width: | Height: | Size: 665 B |
After Width: | Height: | Size: 885 B |
After Width: | Height: | Size: 579 B |
After Width: | Height: | Size: 331 B |
After Width: | Height: | Size: 336 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 899 B |
After Width: | Height: | Size: 340 B |
After Width: | Height: | Size: 390 B |
After Width: | Height: | Size: 565 B |
After Width: | Height: | Size: 1011 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 768 B |
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* BeDecoder.java
|
||||
*
|
||||
* Created on May 30, 2003, 2:44 PM
|
||||
* Copyright (C) 2003, 2004, 2005, 2006 Aelitis, All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* AELITIS, SAS au capital de 46,603.30 euros
|
||||
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
|
||||
*/
|
||||
|
||||
package net.sourceforge.filebot.torrent;
|
||||
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* A set of utility methods to decode a bencoded array of byte into a Map. integer are represented as Long, String as byte[], dictionnaries as Map, and list as List.
|
||||
*
|
||||
* @author TdC_VgA
|
||||
*
|
||||
*/
|
||||
public class BDecoder {
|
||||
|
||||
private boolean recovery_mode;
|
||||
|
||||
private static final Charset BINARY_CHARSET = Charset.forName("ISO-8859-1");
|
||||
|
||||
|
||||
public static Map<?, ?> decode(byte[] data)
|
||||
|
||||
throws IOException {
|
||||
return (new BDecoder().decodeByteArray(data));
|
||||
}
|
||||
|
||||
|
||||
public static Map<?, ?> decode(BufferedInputStream is)
|
||||
|
||||
throws IOException {
|
||||
return (new BDecoder().decodeStream(is));
|
||||
}
|
||||
|
||||
|
||||
public BDecoder() {
|
||||
}
|
||||
|
||||
|
||||
public Map<?, ?> decodeByteArray(byte[] data)
|
||||
|
||||
throws IOException {
|
||||
return (decode(new ByteArrayInputStream(data)));
|
||||
}
|
||||
|
||||
|
||||
public Map<?, ?> decodeStream(BufferedInputStream data)
|
||||
|
||||
throws IOException {
|
||||
Object res = decodeInputStream(data, 0);
|
||||
|
||||
if (res == null)
|
||||
throw (new IOException("BDecoder: zero length file"));
|
||||
else if (!(res instanceof Map))
|
||||
throw (new IOException("BDecoder: top level isn't a Map"));
|
||||
|
||||
return ((Map<?, ?>) res);
|
||||
}
|
||||
|
||||
|
||||
private Map<?, ?> decode(ByteArrayInputStream data)
|
||||
|
||||
throws IOException {
|
||||
Object res = decodeInputStream(data, 0);
|
||||
|
||||
if (res == null)
|
||||
throw (new IOException("BDecoder: zero length file"));
|
||||
else if (!(res instanceof Map))
|
||||
throw (new IOException("BDecoder: top level isn't a Map"));
|
||||
|
||||
return ((Map<?, ?>) res);
|
||||
}
|
||||
|
||||
|
||||
private Object decodeInputStream(InputStream bais, int nesting)
|
||||
|
||||
throws IOException {
|
||||
if (!bais.markSupported())
|
||||
throw new IOException("InputStream must support the mark() method");
|
||||
|
||||
// set a mark
|
||||
bais.mark(Integer.MAX_VALUE);
|
||||
|
||||
// read a byte
|
||||
int tempByte = bais.read();
|
||||
|
||||
// decide what to do
|
||||
switch (tempByte) {
|
||||
case 'd':
|
||||
// create a new dictionary object
|
||||
Map<String, Object> tempMap = new HashMap<String, Object>();
|
||||
|
||||
try {
|
||||
// get the key
|
||||
byte[] tempByteArray = null;
|
||||
|
||||
while ((tempByteArray = (byte[]) decodeInputStream(bais, nesting + 1)) != null) {
|
||||
|
||||
// decode some more
|
||||
|
||||
Object value = decodeInputStream(bais, nesting + 1);
|
||||
|
||||
// add the value to the map
|
||||
|
||||
CharBuffer cb = BINARY_CHARSET.decode(ByteBuffer.wrap(tempByteArray));
|
||||
|
||||
String key = new String(cb.array(), 0, cb.limit());
|
||||
|
||||
tempMap.put(key, value);
|
||||
}
|
||||
|
||||
if (bais.available() < nesting)
|
||||
throw (new IOException("BDecoder: invalid input data, 'e' missing from end of dictionary"));
|
||||
} catch (Throwable e) {
|
||||
|
||||
if (!recovery_mode) {
|
||||
|
||||
if (e instanceof IOException)
|
||||
throw ((IOException) e);
|
||||
|
||||
throw (new IOException(e));
|
||||
}
|
||||
}
|
||||
|
||||
// return the map
|
||||
return tempMap;
|
||||
|
||||
case 'l':
|
||||
// create the list
|
||||
List<Object> tempList = new ArrayList<Object>();
|
||||
|
||||
try {
|
||||
// create the key
|
||||
Object tempElement = null;
|
||||
while ((tempElement = decodeInputStream(bais, nesting + 1)) != null)
|
||||
// add the element
|
||||
tempList.add(tempElement);
|
||||
|
||||
if (bais.available() < nesting)
|
||||
throw (new IOException("BDecoder: invalid input data, 'e' missing from end of list"));
|
||||
} catch (Throwable e) {
|
||||
|
||||
if (!recovery_mode) {
|
||||
|
||||
if (e instanceof IOException)
|
||||
throw ((IOException) e);
|
||||
|
||||
throw (new IOException(e));
|
||||
}
|
||||
}
|
||||
// return the list
|
||||
return tempList;
|
||||
|
||||
case 'e':
|
||||
case -1:
|
||||
return null;
|
||||
|
||||
case 'i':
|
||||
return new Long(getNumberFromStream(bais, 'e'));
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
// move back one
|
||||
bais.reset();
|
||||
// get the string
|
||||
return getByteArrayFromStream(bais);
|
||||
|
||||
default: {
|
||||
|
||||
int rem_len = bais.available();
|
||||
|
||||
if (rem_len > 256)
|
||||
rem_len = 256;
|
||||
|
||||
byte[] rem_data = new byte[rem_len];
|
||||
|
||||
bais.read(rem_data);
|
||||
|
||||
throw (new IOException("BDecoder: unknown command '" + tempByte + ", remainder = " + new String(rem_data)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private long getNumberFromStream(InputStream bais, char parseChar) throws IOException {
|
||||
int length = 0;
|
||||
|
||||
// place a mark
|
||||
bais.mark(Integer.MAX_VALUE);
|
||||
|
||||
int tempByte = bais.read();
|
||||
while ((tempByte != parseChar) && (tempByte >= 0)) {
|
||||
tempByte = bais.read();
|
||||
length++;
|
||||
}
|
||||
|
||||
// are we at the end of the stream?
|
||||
if (tempByte < 0)
|
||||
return -1;
|
||||
|
||||
// reset the mark
|
||||
bais.reset();
|
||||
|
||||
// get the length
|
||||
byte[] tempArray = new byte[length];
|
||||
int count = 0;
|
||||
int len = 0;
|
||||
|
||||
// get the string
|
||||
while ((count != length) && ((len = bais.read(tempArray, count, length - count)) > 0))
|
||||
count += len;
|
||||
|
||||
// jump ahead in the stream to compensate for the :
|
||||
bais.skip(1);
|
||||
|
||||
// return the value
|
||||
|
||||
CharBuffer cb = BINARY_CHARSET.decode(ByteBuffer.wrap(tempArray));
|
||||
|
||||
String str_value = new String(cb.array(), 0, cb.limit());
|
||||
|
||||
return Long.parseLong(str_value);
|
||||
}
|
||||
|
||||
|
||||
private byte[] getByteArrayFromStream(InputStream bais) throws IOException {
|
||||
int length = (int) getNumberFromStream(bais, ':');
|
||||
|
||||
if (length < 0)
|
||||
return null;
|
||||
|
||||
// note that torrent hashes can be big (consider a 55GB file with 2MB
|
||||
// pieces
|
||||
// this generates a pieces hash of 1/2 meg
|
||||
|
||||
if (length > 8 * 1024 * 1024)
|
||||
throw (new IOException("Byte array length too large (" + length + ")"));
|
||||
|
||||
byte[] tempArray = new byte[length];
|
||||
int count = 0;
|
||||
int len = 0;
|
||||
// get the string
|
||||
while ((count != length) && ((len = bais.read(tempArray, count, length - count)) > 0))
|
||||
count += len;
|
||||
|
||||
if (count != tempArray.length)
|
||||
throw (new IOException("BDecoder::getByteArrayFromStream: truncated"));
|
||||
|
||||
return tempArray;
|
||||
}
|
||||
|
||||
|
||||
public void setRecoveryMode(boolean r) {
|
||||
recovery_mode = r;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
|
||||
package net.sourceforge.filebot.torrent;
|
||||
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class Torrent {
|
||||
|
||||
private String name;
|
||||
private String encoding;
|
||||
private String createdBy;
|
||||
private String announce;
|
||||
private String comment;
|
||||
private Long creationDate;
|
||||
|
||||
private List<Entry> files;
|
||||
|
||||
private boolean singleFileTorrent;
|
||||
|
||||
|
||||
public Torrent(File torrent) throws IOException {
|
||||
FileInputStream in = new FileInputStream(torrent);
|
||||
Map<?, ?> torrentMap = null;
|
||||
|
||||
try {
|
||||
torrentMap = BDecoder.decode(new BufferedInputStream(in));
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
|
||||
Charset charset = Charset.forName("UTF-8");
|
||||
|
||||
encoding = decodeString(torrentMap.get("encoding"), charset);
|
||||
|
||||
try {
|
||||
charset = Charset.forName(encoding);
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
|
||||
createdBy = decodeString(torrentMap.get("created by"), charset);
|
||||
announce = decodeString(torrentMap.get("announce"), charset);
|
||||
comment = decodeString(torrentMap.get("comment"), charset);
|
||||
creationDate = decodeLong(torrentMap.get("creation date"));
|
||||
|
||||
Map<?, ?> infoMap = (Map<?, ?>) torrentMap.get("info");
|
||||
|
||||
name = decodeString(infoMap.get("name"), charset);
|
||||
|
||||
if (infoMap.containsKey("files")) {
|
||||
singleFileTorrent = false;
|
||||
|
||||
files = new ArrayList<Entry>();
|
||||
|
||||
for (Object fileMapObject : (List<?>) infoMap.get("files")) {
|
||||
Map<?, ?> fileMap = (Map<?, ?>) fileMapObject;
|
||||
List<?> pathList = (List<?>) fileMap.get("path");
|
||||
|
||||
StringBuffer pathBuffer = new StringBuffer();
|
||||
String entryName = null;
|
||||
|
||||
Iterator<?> iterator = pathList.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
String pathElement = decodeString(iterator.next(), charset);
|
||||
|
||||
if (iterator.hasNext()) {
|
||||
pathBuffer.append(pathElement);
|
||||
pathBuffer.append("/");
|
||||
} else {
|
||||
// the last element in the path list is the filename
|
||||
entryName = pathElement;
|
||||
}
|
||||
}
|
||||
|
||||
Long length = decodeLong(fileMap.get("length"));
|
||||
|
||||
files.add(new Entry(entryName, length, pathBuffer.toString()));
|
||||
}
|
||||
} else {
|
||||
// single file torrent
|
||||
singleFileTorrent = true;
|
||||
files = new ArrayList<Entry>(1);
|
||||
|
||||
Long length = decodeLong(infoMap.get("length"));
|
||||
|
||||
files.add(new Entry(name, length, ""));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String decodeString(Object bytearray, Charset charset) {
|
||||
if (bytearray == null)
|
||||
return null;
|
||||
|
||||
return new String((byte[]) bytearray, charset);
|
||||
}
|
||||
|
||||
|
||||
private Long decodeLong(Object number) {
|
||||
if (number == null)
|
||||
return null;
|
||||
|
||||
return (Long) number;
|
||||
}
|
||||
|
||||
|
||||
public String getAnnounce() {
|
||||
return announce;
|
||||
}
|
||||
|
||||
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
|
||||
public String getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
|
||||
public Long getCreationDate() {
|
||||
return creationDate;
|
||||
}
|
||||
|
||||
|
||||
public String getEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
|
||||
public List<Entry> getFiles() {
|
||||
return files;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public boolean isSingleFileTorrent() {
|
||||
return singleFileTorrent;
|
||||
}
|
||||
|
||||
|
||||
public static class Entry {
|
||||
|
||||
private String name;
|
||||
private long length;
|
||||
private String path;
|
||||
|
||||
|
||||
public Entry(String name, Long length, String path) {
|
||||
this.name = name;
|
||||
this.length = length;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
|
||||
public Long getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
|
||||
package net.sourceforge.filebot.ui;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
import net.sourceforge.filebot.ui.sal.FileTransferable;
|
||||
import net.sourceforge.filebot.ui.sal.Saveable;
|
||||
import net.sourceforge.filebot.ui.transferablepolicies.NullTransferablePolicy;
|
||||
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
|
||||
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicySupport;
|
||||
import net.sourceforge.tuned.ui.FancyListCellRenderer;
|
||||
|
||||
|
||||
public class FileBotList extends JPanel implements Saveable, TransferablePolicySupport {
|
||||
|
||||
private JList list = new JList(new DefaultListModel());
|
||||
|
||||
private TitledBorder titledBorder;
|
||||
|
||||
private String title;
|
||||
|
||||
private TransferablePolicy transferablePolicy = new NullTransferablePolicy();
|
||||
|
||||
|
||||
public FileBotList(boolean enableDrop, boolean enableDrag, boolean initRemoveAction) {
|
||||
this(enableDrop, enableDrag, initRemoveAction, true);
|
||||
}
|
||||
|
||||
|
||||
public FileBotList(boolean enableDrop, boolean enableDrag, boolean initRemoveAction, boolean border) {
|
||||
super(new BorderLayout());
|
||||
|
||||
JScrollPane listScrollPane = new JScrollPane(list);
|
||||
|
||||
if (border) {
|
||||
titledBorder = new TitledBorder("");
|
||||
setBorder(titledBorder);
|
||||
} else {
|
||||
listScrollPane.setBorder(BorderFactory.createEmptyBorder());
|
||||
}
|
||||
|
||||
list.setCellRenderer(new FancyListCellRenderer());
|
||||
list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
add(listScrollPane, BorderLayout.CENTER);
|
||||
|
||||
TransferablePolicySupport handlerTransferablePolicySupport = null;
|
||||
Saveable handlerSaveable = null;
|
||||
|
||||
if (enableDrop) {
|
||||
handlerTransferablePolicySupport = this;
|
||||
}
|
||||
|
||||
if (enableDrag) {
|
||||
handlerSaveable = this;
|
||||
}
|
||||
|
||||
list.setTransferHandler(new FileBotTransferHandler(handlerTransferablePolicySupport, handlerSaveable));
|
||||
|
||||
if (handlerSaveable != null)
|
||||
MouseDragRecognizeListener.createForComponent(this.getListComponent());
|
||||
|
||||
if (initRemoveAction) {
|
||||
// Shortcut DELETE
|
||||
FileBotUtil.registerActionForKeystroke(this, KeyStroke.getKeyStroke("pressed DELETE"), removeAction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public JList getListComponent() {
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
public void setTransferablePolicy(TransferablePolicy transferablePolicy) {
|
||||
this.transferablePolicy = transferablePolicy;
|
||||
}
|
||||
|
||||
|
||||
public TransferablePolicy getTransferablePolicy() {
|
||||
return transferablePolicy;
|
||||
}
|
||||
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
|
||||
if (titledBorder != null)
|
||||
titledBorder.setTitle(title);
|
||||
|
||||
if (isVisible()) {
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public DefaultListModel getModel() {
|
||||
return (DefaultListModel) list.getModel();
|
||||
}
|
||||
|
||||
|
||||
public void save(File file) {
|
||||
try {
|
||||
PrintStream out = new PrintStream(file);
|
||||
|
||||
DefaultListModel model = getModel();
|
||||
|
||||
for (int i = 0; i < model.getSize(); ++i)
|
||||
out.println(model.get(i).toString());
|
||||
|
||||
out.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getDefaultFileName() {
|
||||
return title + ".txt";
|
||||
}
|
||||
|
||||
|
||||
public boolean isSaveable() {
|
||||
return !getModel().isEmpty();
|
||||
}
|
||||
|
||||
|
||||
public void load(List<File> files) {
|
||||
FileTransferable tr = new FileTransferable(files);
|
||||
|
||||
if (transferablePolicy.accept(tr))
|
||||
transferablePolicy.handleTransferable(tr, false);
|
||||
}
|
||||
|
||||
private final AbstractAction removeAction = new AbstractAction("Remove") {
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int index = list.getSelectedIndex();
|
||||
Object values[] = list.getSelectedValues();
|
||||
|
||||
for (Object value : values)
|
||||
getModel().removeElement(value);
|
||||
|
||||
int maxIndex = list.getModel().getSize() - 1;
|
||||
|
||||
if (index > maxIndex)
|
||||
index = maxIndex;
|
||||
|
||||
list.setSelectedIndex(index);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
package net.sourceforge.filebot.ui;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
|
||||
public class FileBotPanel extends JPanel {
|
||||
|
||||
private String text;
|
||||
|
||||
private Icon icon;
|
||||
|
||||
|
||||
public FileBotPanel(String text, Icon icon) {
|
||||
super(new BorderLayout(10, 20));
|
||||
this.text = text;
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
|
||||
public Icon getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
|
||||
package net.sourceforge.filebot.ui;
|
||||
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.dnd.DropTarget;
|
||||
import java.awt.dnd.DropTargetAdapter;
|
||||
import java.awt.dnd.DropTargetDragEvent;
|
||||
import java.awt.dnd.DropTargetDropEvent;
|
||||
import java.awt.dnd.DropTargetEvent;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.Timer;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import net.sourceforge.filebot.ui.panel.analyze.AnalyzePanel;
|
||||
import net.sourceforge.filebot.ui.panel.create.CreatePanel;
|
||||
import net.sourceforge.filebot.ui.panel.list.ListPanel;
|
||||
import net.sourceforge.filebot.ui.panel.rename.RenamePanel;
|
||||
import net.sourceforge.filebot.ui.panel.search.SearchPanel;
|
||||
import net.sourceforge.filebot.ui.panel.sfv.SfvPanel;
|
||||
import net.sourceforge.tuned.ui.FancyListCellRenderer;
|
||||
import net.sourceforge.tuned.ui.GradientStyle;
|
||||
|
||||
|
||||
public class FileBotPanelSelectionList extends JList {
|
||||
|
||||
private static final int SELECTDELAY_ON_DRAG_OVER = 300;
|
||||
|
||||
|
||||
public FileBotPanelSelectionList() {
|
||||
DefaultListModel model = new DefaultListModel();
|
||||
setModel(model);
|
||||
|
||||
setCellRenderer(new PanelCellRenderer());
|
||||
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
|
||||
setBorder(new EmptyBorder(4, 5, 4, 5));
|
||||
|
||||
new DropTarget(this, new DragDropListener());
|
||||
|
||||
model.addElement(new ListPanel());
|
||||
model.addElement(new RenamePanel());
|
||||
model.addElement(new AnalyzePanel());
|
||||
model.addElement(new SearchPanel());
|
||||
model.addElement(new CreatePanel());
|
||||
model.addElement(new SfvPanel());
|
||||
}
|
||||
|
||||
|
||||
private class PanelCellRenderer extends FancyListCellRenderer {
|
||||
|
||||
public PanelCellRenderer() {
|
||||
super(10, Color.decode("#163264"), GradientStyle.TOP_TO_BOTTOM);
|
||||
setVerticalTextPosition(SwingConstants.BOTTOM);
|
||||
setHorizontalTextPosition(SwingConstants.CENTER);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
|
||||
FileBotPanel panel = (FileBotPanel) value;
|
||||
setText(panel.getText());
|
||||
setIcon(panel.getIcon());
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class DragDropListener extends DropTargetAdapter implements ActionListener {
|
||||
|
||||
private boolean selectEnabled = false;
|
||||
|
||||
private Timer timer = new Timer(SELECTDELAY_ON_DRAG_OVER, this);
|
||||
|
||||
|
||||
public DragDropListener() {
|
||||
timer.setRepeats(false);
|
||||
}
|
||||
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
selectEnabled = true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void dragOver(DropTargetDragEvent dtde) {
|
||||
if (selectEnabled) {
|
||||
int index = locationToIndex(dtde.getLocation());
|
||||
setSelectedIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void dragEnter(DropTargetDragEvent dtde) {
|
||||
timer.start();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void dragExit(DropTargetEvent dte) {
|
||||
timer.stop();
|
||||
selectEnabled = false;
|
||||
}
|
||||
|
||||
|
||||
public void drop(DropTargetDropEvent dtde) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
|
||||
package net.sourceforge.filebot.ui;
|
||||
|
||||
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.dnd.InvalidDnDOperationException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.TransferHandler;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import net.sourceforge.filebot.ui.sal.FileTransferable;
|
||||
import net.sourceforge.filebot.ui.sal.Saveable;
|
||||
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicySupport;
|
||||
|
||||
|
||||
public class FileBotTransferHandler extends TransferHandler {
|
||||
|
||||
private TransferablePolicySupport transferablePolicySupport;
|
||||
|
||||
private Saveable saveable;
|
||||
|
||||
private boolean dragging;
|
||||
|
||||
private String tmpdir = System.getProperty("java.io.tmpdir");
|
||||
|
||||
|
||||
public FileBotTransferHandler(TransferablePolicySupport transferablePolicySupport, Saveable saveable) {
|
||||
this.transferablePolicySupport = transferablePolicySupport;
|
||||
this.saveable = saveable;
|
||||
}
|
||||
|
||||
private boolean canImportCache = false;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canImport(TransferSupport support) {
|
||||
// show "drop allowed" mousecursor when dragging even though drop is not allowed
|
||||
if (dragging)
|
||||
return true;
|
||||
|
||||
if (transferablePolicySupport == null)
|
||||
return false;
|
||||
|
||||
if (support.isDrop())
|
||||
support.setShowDropLocation(false);
|
||||
|
||||
Transferable t = support.getTransferable();
|
||||
|
||||
try {
|
||||
canImportCache = transferablePolicySupport.getTransferablePolicy().accept(t);
|
||||
} catch (InvalidDnDOperationException e) {
|
||||
// for some reason the last transferable has no drop current
|
||||
}
|
||||
|
||||
return canImportCache;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean importData(TransferSupport support) {
|
||||
if (dragging)
|
||||
return false;
|
||||
|
||||
if (!canImport(support))
|
||||
return false;
|
||||
|
||||
boolean add = false;
|
||||
|
||||
if (support.isDrop())
|
||||
add = support.getDropAction() == COPY;
|
||||
|
||||
Transferable t = support.getTransferable();
|
||||
|
||||
return transferablePolicySupport.getTransferablePolicy().handleTransferable(t, add);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void exportDone(JComponent source, Transferable data, int action) {
|
||||
dragging = false;
|
||||
|
||||
if (data == null)
|
||||
return;
|
||||
|
||||
try {
|
||||
List<?> list = (List<?>) data.getTransferData(DataFlavor.javaFileListFlavor);
|
||||
|
||||
for (Object object : list) {
|
||||
File temporaryFile = (File) object;
|
||||
temporaryFile.deleteOnExit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getSourceActions(JComponent c) {
|
||||
if (saveable == null || !saveable.isSaveable())
|
||||
return NONE;
|
||||
|
||||
return MOVE | COPY;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void exportToClipboard(JComponent comp, Clipboard clip, int action) throws IllegalStateException {
|
||||
ArrayList<String> lines = new ArrayList<String>();
|
||||
|
||||
if (comp instanceof JList) {
|
||||
JList list = (JList) comp;
|
||||
for (Object value : list.getSelectedValues()) {
|
||||
lines.add(value.toString());
|
||||
}
|
||||
} else if (comp instanceof JTree) {
|
||||
JTree tree = (JTree) comp;
|
||||
for (TreePath path : tree.getSelectionPaths()) {
|
||||
lines.add(path.getPathComponent(path.getPathCount() - 1).toString());
|
||||
}
|
||||
} else if (comp instanceof JTable) {
|
||||
JTable table = (JTable) comp;
|
||||
|
||||
for (int row : table.getSelectedRows()) {
|
||||
StringBuffer b = new StringBuffer();
|
||||
int maxCol = table.getColumnCount() - 1;
|
||||
for (int col = 0; col <= maxCol; col++) {
|
||||
b.append(table.getModel().getValueAt(row, col));
|
||||
|
||||
if (col != maxCol)
|
||||
b.append("\t");
|
||||
}
|
||||
|
||||
lines.add(b.toString());
|
||||
}
|
||||
}
|
||||
|
||||
StringBuffer b = new StringBuffer();
|
||||
Iterator<String> it = lines.iterator();
|
||||
|
||||
while (it.hasNext()) {
|
||||
b.append(it.next());
|
||||
|
||||
if (it.hasNext())
|
||||
b.append("\n");
|
||||
}
|
||||
|
||||
clip.setContents(new StringSelection(b.toString()), null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Transferable createTransferable(JComponent c) {
|
||||
dragging = true;
|
||||
|
||||
try {
|
||||
File temporaryFile = new File(tmpdir, saveable.getDefaultFileName());
|
||||
temporaryFile.createNewFile();
|
||||
|
||||
saveable.save(temporaryFile);
|
||||
return new FileTransferable(temporaryFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,236 @@
|
|||
|
||||
package net.sourceforge.filebot.ui;
|
||||
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.awt.Font;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.File;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreeModel;
|
||||
import javax.swing.tree.TreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
import javax.swing.tree.TreeSelectionModel;
|
||||
|
||||
import net.sourceforge.filebot.resources.ResourceManager;
|
||||
import net.sourceforge.filebot.ui.transferablepolicies.NullTransferablePolicy;
|
||||
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
|
||||
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicySupport;
|
||||
|
||||
|
||||
public class FileBotTree extends JTree implements TransferablePolicySupport {
|
||||
|
||||
private TransferablePolicy transferablePolicy = new NullTransferablePolicy();
|
||||
|
||||
|
||||
public FileBotTree() {
|
||||
super(new DefaultTreeModel(new DefaultMutableTreeNode()));
|
||||
getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
|
||||
setCellRenderer(new FileBotTreeCellRenderer());
|
||||
setShowsRootHandles(true);
|
||||
setRootVisible(false);
|
||||
setRowHeight(22);
|
||||
|
||||
setTransferHandler(new FileBotTransferHandler(this, null));
|
||||
|
||||
addMouseListener(new ExpandCollapsePopupListener());
|
||||
}
|
||||
|
||||
|
||||
public void clear() {
|
||||
setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
|
||||
}
|
||||
|
||||
|
||||
public void setTransferablePolicy(TransferablePolicy transferablePolicy) {
|
||||
this.transferablePolicy = transferablePolicy;
|
||||
}
|
||||
|
||||
|
||||
public TransferablePolicy getTransferablePolicy() {
|
||||
return transferablePolicy;
|
||||
}
|
||||
|
||||
|
||||
public LinkedList<File> convertToList() {
|
||||
LinkedList<File> list = new LinkedList<File>();
|
||||
TreeModel m = getModel();
|
||||
walk(m, m.getRoot(), list);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String convertValueToText(Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
||||
if (value instanceof DefaultMutableTreeNode) {
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
|
||||
|
||||
Object userObject = node.getUserObject();
|
||||
|
||||
if (userObject != null && userObject instanceof File) {
|
||||
File file = (File) node.getUserObject();
|
||||
return file.getName();
|
||||
}
|
||||
}
|
||||
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
|
||||
private void walk(TreeModel model, Object o, LinkedList<File> list) {
|
||||
int cc = model.getChildCount(o);
|
||||
|
||||
for (int i = 0; i < cc; i++) {
|
||||
DefaultMutableTreeNode child = (DefaultMutableTreeNode) model.getChild(o, i);
|
||||
if (model.isLeaf(child))
|
||||
list.add((File) child.getUserObject());
|
||||
else
|
||||
walk(model, child, list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void expandOrCollapseAll(boolean expand) {
|
||||
TreeNode node = (TreeNode) getModel().getRoot();
|
||||
Enumeration<?> e = node.children();
|
||||
|
||||
while (e.hasMoreElements()) {
|
||||
TreeNode n = (TreeNode) e.nextElement();
|
||||
TreePath path = new TreePath(node).pathByAddingChild(n);
|
||||
expandOrCollapseAllImpl(path, expand);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void expandOrCollapseAllImpl(TreePath parent, boolean expand) {
|
||||
// Traverse children
|
||||
TreeNode node = (TreeNode) parent.getLastPathComponent();
|
||||
if (node.getChildCount() >= 0)
|
||||
for (Enumeration<?> e = node.children(); e.hasMoreElements();) {
|
||||
TreeNode n = (TreeNode) e.nextElement();
|
||||
TreePath path = parent.pathByAddingChild(n);
|
||||
expandOrCollapseAllImpl(path, expand);
|
||||
}
|
||||
|
||||
// Expansion or collapse must be done bottom-up
|
||||
if (expand)
|
||||
expandPath(parent);
|
||||
else
|
||||
collapsePath(parent);
|
||||
}
|
||||
|
||||
|
||||
private class ExpandCollapsePopup extends JPopupMenu {
|
||||
|
||||
public ExpandCollapsePopup() {
|
||||
if (getSelectionCount() >= 1) {
|
||||
Object pathComponent = getLastSelectedPathComponent();
|
||||
|
||||
if (pathComponent instanceof DefaultMutableTreeNode) {
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode) pathComponent;
|
||||
|
||||
Object userObject = node.getUserObject();
|
||||
|
||||
if (userObject instanceof File) {
|
||||
File file = (File) userObject;
|
||||
|
||||
if (file.isFile()) {
|
||||
JMenuItem openItem = new JMenuItem(new OpenAction("Open", file));
|
||||
openItem.setFont(openItem.getFont().deriveFont(Font.BOLD));
|
||||
|
||||
add(openItem);
|
||||
add(new OpenAction("Open Folder", file.getParentFile()));
|
||||
addSeparator();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add(new ExpandOrCollapseAction(true));
|
||||
add(new ExpandOrCollapseAction(false));
|
||||
}
|
||||
|
||||
|
||||
private class OpenAction extends AbstractAction {
|
||||
|
||||
private File file;
|
||||
|
||||
|
||||
public OpenAction(String text, File file) {
|
||||
super(text);
|
||||
this.file = file;
|
||||
|
||||
if (file == null)
|
||||
setEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
Desktop.getDesktop().open(file);
|
||||
} catch (Exception ex) {
|
||||
MessageManager.showWarning(ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class ExpandOrCollapseAction extends AbstractAction {
|
||||
|
||||
private boolean expand;
|
||||
|
||||
|
||||
public ExpandOrCollapseAction(boolean expand) {
|
||||
this.expand = expand;
|
||||
|
||||
if (expand) {
|
||||
putValue(SMALL_ICON, ResourceManager.getIcon("tree.expand"));
|
||||
putValue(NAME, "Expand all");
|
||||
} else {
|
||||
putValue(SMALL_ICON, ResourceManager.getIcon("tree.collapse"));
|
||||
putValue(NAME, "Collapse all");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
expandOrCollapseAll(expand);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private class ExpandCollapsePopupListener extends MouseAdapter {
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
if (SwingUtilities.isRightMouseButton(e)) {
|
||||
ExpandCollapsePopup popup = new ExpandCollapsePopup();
|
||||
popup.show(e.getComponent(), e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (SwingUtilities.isRightMouseButton(e)) {
|
||||
TreePath path = getPathForLocation(e.getX(), e.getY());
|
||||
setSelectionPath(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
|
||||
package net.sourceforge.filebot.ui;
|
||||
|
||||
|
||||
import java.awt.Component;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
import net.sourceforge.filebot.resources.ResourceManager;
|
||||
import net.sourceforge.tuned.ui.FancyTreeCellRenderer;
|
||||
import net.sourceforge.tuned.ui.GradientStyle;
|
||||
|
||||
|
||||
public class FileBotTreeCellRenderer extends FancyTreeCellRenderer {
|
||||
|
||||
public FileBotTreeCellRenderer() {
|
||||
super(GradientStyle.TOP_TO_BOTTOM);
|
||||
openIcon = ResourceManager.getIcon("tree.open");
|
||||
closedIcon = ResourceManager.getIcon("tree.closed");
|
||||
leafIcon = ResourceManager.getIcon("tree.leaf");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) {
|
||||
if (leaf && isFolder(value))
|
||||
super.getTreeCellRendererComponent(tree, value, sel, true, false, row, hasFocus);
|
||||
else
|
||||
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
private boolean isFolder(Object value) {
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
|
||||
Object object = node.getUserObject();
|
||||
|
||||
if (object instanceof File)
|
||||
return ((File) object).isDirectory();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
package net.sourceforge.filebot.ui;
|
||||
|
||||
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
|
||||
public class FileBotUtil {
|
||||
|
||||
private FileBotUtil() {
|
||||
// hide construktor
|
||||
}
|
||||
|
||||
|
||||
public static void registerActionForKeystroke(JComponent component, KeyStroke keystroke, Action action) {
|
||||
Integer key = action.hashCode();
|
||||
component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(keystroke, key);
|
||||
component.getActionMap().put(key, action);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
|
||||
package net.sourceforge.filebot.ui;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.CardLayout;
|
||||
import java.awt.Image;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.ListModel;
|
||||
import javax.swing.OverlayLayout;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import net.sourceforge.filebot.resources.ResourceManager;
|
||||
import net.sourceforge.tuned.ui.ShadowBorder;
|
||||
|
||||
|
||||
public class FileBotWindow extends JFrame implements ListSelectionListener {
|
||||
|
||||
private JPanel pagePanel = new JPanel(new CardLayout());
|
||||
|
||||
private FileBotPanelSelectionList selectionListPanel = new FileBotPanelSelectionList();
|
||||
|
||||
private HeaderPanel headerPanel = new HeaderPanel();
|
||||
|
||||
|
||||
public FileBotWindow() {
|
||||
super("FileBot");
|
||||
setLocationByPlatform(true);
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
|
||||
ArrayList<Image> icons = new ArrayList<Image>(2);
|
||||
icons.add(ResourceManager.getImage("window.icon.small"));
|
||||
icons.add(ResourceManager.getImage("window.icon.big"));
|
||||
setIconImages(icons);
|
||||
|
||||
selectionListPanel.addListSelectionListener(this);
|
||||
|
||||
JComponent contentPane = createContentPane();
|
||||
|
||||
setContentPane(contentPane);
|
||||
|
||||
// Shortcut ESC
|
||||
FileBotUtil.registerActionForKeystroke(contentPane, KeyStroke.getKeyStroke("released ESCAPE"), closeAction);
|
||||
|
||||
setSize(760, 615);
|
||||
|
||||
selectionListPanel.setSelectedIndex(3);
|
||||
}
|
||||
|
||||
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
FileBotPanel currentPanel = (FileBotPanel) selectionListPanel.getSelectedValue();
|
||||
|
||||
headerPanel.setTitle(currentPanel.getText());
|
||||
CardLayout cardLayout = (CardLayout) pagePanel.getLayout();
|
||||
cardLayout.show(pagePanel, currentPanel.getText());
|
||||
|
||||
JComponent c = (JComponent) getContentPane();
|
||||
c.updateUI();
|
||||
}
|
||||
|
||||
|
||||
private JComponent createSelectionListLayer() {
|
||||
JPanel selectionListLayer = new JPanel(new BorderLayout());
|
||||
selectionListLayer.setOpaque(false);
|
||||
|
||||
JPanel shadowBorderPanel = new JPanel(new BorderLayout());
|
||||
shadowBorderPanel.setOpaque(false);
|
||||
|
||||
JScrollPane selectListScrollPane = new JScrollPane(selectionListPanel);
|
||||
selectListScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
selectListScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
|
||||
shadowBorderPanel.add(selectListScrollPane, BorderLayout.CENTER);
|
||||
shadowBorderPanel.setBorder(new ShadowBorder());
|
||||
|
||||
selectionListLayer.setBorder(new EmptyBorder(10, 6, 12, 0));
|
||||
selectionListLayer.add(shadowBorderPanel, BorderLayout.WEST);
|
||||
|
||||
selectionListLayer.setAlignmentX(0.0f);
|
||||
selectionListLayer.setAlignmentY(0.0f);
|
||||
selectionListLayer.setMaximumSize(selectionListLayer.getPreferredSize());
|
||||
|
||||
return selectionListLayer;
|
||||
}
|
||||
|
||||
|
||||
private JComponent createPageLayer() {
|
||||
JPanel pageLayer = new JPanel(new BorderLayout());
|
||||
|
||||
pagePanel.setBorder(new EmptyBorder(10, 110, 10, 10));
|
||||
|
||||
pageLayer.add(headerPanel, BorderLayout.NORTH);
|
||||
pageLayer.add(pagePanel, BorderLayout.CENTER);
|
||||
|
||||
ListModel model = selectionListPanel.getModel();
|
||||
|
||||
for (int i = 0; i < model.getSize(); i++) {
|
||||
FileBotPanel panel = (FileBotPanel) model.getElementAt(i);
|
||||
panel.setVisible(false);
|
||||
pagePanel.add(panel, panel.getText());
|
||||
}
|
||||
|
||||
pageLayer.setAlignmentX(0.0f);
|
||||
pageLayer.setAlignmentY(0.0f);
|
||||
|
||||
return pageLayer;
|
||||
}
|
||||
|
||||
|
||||
private JComponent createContentPane() {
|
||||
JPanel contentPane = new JPanel();
|
||||
contentPane.setLayout(new OverlayLayout(contentPane));
|
||||
|
||||
contentPane.add(createSelectionListLayer());
|
||||
contentPane.add(createPageLayer());
|
||||
|
||||
return contentPane;
|
||||
}
|
||||
|
||||
private final AbstractAction closeAction = new AbstractAction("Close") {
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
setVisible(false);
|
||||
dispose();
|
||||
System.exit(0);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
|
||||
package net.sourceforge.filebot.ui;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.text.NumberFormat;
|
||||
|
||||
|
||||
public class FileFormat {
|
||||
|
||||
private static NumberFormat nf = NumberFormat.getNumberInstance();
|
||||
|
||||
public final static long KILO = 1024;
|
||||
|
||||
public final static long MEGA = KILO * 1024;
|
||||
|
||||
public final static long GIGA = MEGA * 1024;
|
||||
|
||||
static {
|
||||
nf.setMaximumFractionDigits(0);
|
||||
}
|
||||
|
||||
|
||||
public static String formatSize(long size) {
|
||||
if (size >= MEGA)
|
||||
return nf.format((double) size / MEGA) + " MB";
|
||||
else if (size >= KILO)
|
||||
return nf.format((double) size / KILO) + " KB";
|
||||
else
|
||||
return nf.format((double) size) + " Byte";
|
||||
}
|
||||
|
||||
|
||||
public static String formatName(File f) {
|
||||
String name = f.getName();
|
||||
|
||||
if (f.isDirectory())
|
||||
return name;
|
||||
|
||||
return getNameWithoutSuffix(name);
|
||||
}
|
||||
|
||||
|
||||
public static String formatNumberOfFiles(int n) {
|
||||
if (n == 1)
|
||||
return n + " file";
|
||||
else
|
||||
return n + " files";
|
||||
}
|
||||
|
||||
|
||||
public static String getSuffix(File f) {
|
||||
return getSuffix(f, false);
|
||||
}
|
||||
|
||||
|
||||
public static String getSuffix(File f, boolean dot) {
|
||||
String name = f.getName();
|
||||
int dotIndex = name.lastIndexOf(".");
|
||||
|
||||
if (dotIndex > 1) {
|
||||
String suffix = name.substring(dotIndex + 1, name.length());
|
||||
if (dot)
|
||||
return "." + suffix;
|
||||
else
|
||||
return suffix;
|
||||
} else
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
public static String getNameWithoutSuffix(String name) {
|
||||
int dotIndex = name.lastIndexOf(".");
|
||||
|
||||
if (dotIndex < 1)
|
||||
return name;
|
||||
|
||||
return name.substring(0, dotIndex);
|
||||
}
|
||||
|
||||
|
||||
public static String getNameWithoutSuffix(File file) {
|
||||
return getNameWithoutSuffix(file.getName());
|
||||
}
|
||||
|
||||
|
||||
public static String getName(File file) {
|
||||
if (!file.getName().isEmpty()) {
|
||||
return file.getName();
|
||||
} else {
|
||||
return file.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
|
||||
package net.sourceforge.filebot.ui;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.LinearGradientPaint;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import net.sourceforge.filebot.resources.ResourceManager;
|
||||
import net.sourceforge.tuned.ui.GradientStyle;
|
||||
import net.sourceforge.tuned.ui.notification.SeparatorBorder;
|
||||
import net.sourceforge.tuned.ui.notification.SeparatorBorder.Position;
|
||||
|
||||
|
||||
public class HeaderPanel extends JPanel {
|
||||
|
||||
private JLabel titleLabel = new JLabel();
|
||||
|
||||
private float[] gradientFractions = { 0.0f, 0.5f, 1.0f };
|
||||
private Color[] gradientColors = { new Color(0xF6F6F6), new Color(0xF8F8F8), new Color(0xF3F3F3) };
|
||||
|
||||
|
||||
public HeaderPanel() {
|
||||
super(new BorderLayout());
|
||||
setBackground(Color.WHITE);
|
||||
|
||||
JPanel centerPanel = new JPanel(new BorderLayout());
|
||||
centerPanel.setOpaque(false);
|
||||
|
||||
titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
titleLabel.setVerticalAlignment(SwingConstants.CENTER);
|
||||
titleLabel.setOpaque(false);
|
||||
titleLabel.setForeground(new Color(0x101010));
|
||||
titleLabel.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 24));
|
||||
|
||||
int margin = 9;
|
||||
titleLabel.setBorder(new EmptyBorder(margin - 1, 90, margin + 1, 0));
|
||||
|
||||
JLabel decorationLabel = new JLabel(ResourceManager.getIcon("decoration.header"));
|
||||
decorationLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
decorationLabel.setVerticalAlignment(SwingConstants.CENTER);
|
||||
|
||||
centerPanel.setBorder(new EmptyBorder(0, 78, 0, 0));
|
||||
centerPanel.add(decorationLabel, BorderLayout.EAST);
|
||||
centerPanel.add(titleLabel, BorderLayout.CENTER);
|
||||
|
||||
add(centerPanel, BorderLayout.CENTER);
|
||||
|
||||
setBorder(new SeparatorBorder(1, new Color(0xB4B4B4), new Color(0xACACAC), GradientStyle.LEFT_TO_RIGHT, Position.BOTTOM));
|
||||
}
|
||||
|
||||
|
||||
public void setTitle(String title) {
|
||||
titleLabel.setText(title);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
|
||||
LinearGradientPaint paint = new LinearGradientPaint(0, 0, getWidth(), 0, gradientFractions, gradientColors);
|
||||
|
||||
g2d.setPaint(paint);
|
||||
g2d.fill(getBounds());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
package net.sourceforge.filebot.ui;
|
||||
|
||||
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
import net.sourceforge.filebot.resources.ResourceManager;
|
||||
import net.sourceforge.tuned.ui.notification.MessageNotification;
|
||||
import net.sourceforge.tuned.ui.notification.NotificationManager;
|
||||
import net.sourceforge.tuned.ui.notification.QueueNotificationLayout;
|
||||
|
||||
|
||||
public class MessageManager {
|
||||
|
||||
private static final int TIMEOUT = 2500;
|
||||
private static final NotificationManager manager = new NotificationManager(new QueueNotificationLayout(SwingConstants.NORTH, SwingConstants.SOUTH));
|
||||
|
||||
|
||||
public static void showInfo(String message) {
|
||||
show(message, ResourceManager.getIcon("message.info"), TIMEOUT);
|
||||
}
|
||||
|
||||
|
||||
public static void showWarning(String message) {
|
||||
show(message, ResourceManager.getIcon("message.warning"), TIMEOUT * 2);
|
||||
}
|
||||
|
||||
|
||||
private static void show(String message, Icon icon, int timeout) {
|
||||
manager.show(new MessageNotification("FileBot", message, icon, timeout));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
package net.sourceforge.filebot.ui;
|
||||
|
||||
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.TransferHandler;
|
||||
|
||||
|
||||
public class MouseDragRecognizeListener extends MouseAdapter {
|
||||
|
||||
private MouseEvent firstMouseEvent = null;
|
||||
|
||||
private int dragShift = 5;
|
||||
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
firstMouseEvent = e;
|
||||
e.consume();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
if (firstMouseEvent != null) {
|
||||
e.consume();
|
||||
int dx = Math.abs(e.getX() - firstMouseEvent.getX());
|
||||
int dy = Math.abs(e.getY() - firstMouseEvent.getY());
|
||||
|
||||
if (dx > dragShift || dy > dragShift) {
|
||||
// This is a drag, not a click.
|
||||
JComponent c = (JComponent) e.getSource();
|
||||
TransferHandler handler = c.getTransferHandler();
|
||||
handler.exportAsDrag(c, firstMouseEvent, TransferHandler.COPY);
|
||||
firstMouseEvent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
firstMouseEvent = null;
|
||||
}
|
||||
|
||||
|
||||
public static void createForComponent(JComponent component) {
|
||||
MouseDragRecognizeListener l = new MouseDragRecognizeListener();
|
||||
|
||||
component.addMouseListener(l);
|
||||
component.addMouseMotionListener(l);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.analyze;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
import net.sourceforge.filebot.resources.ResourceManager;
|
||||
import net.sourceforge.filebot.ui.FileBotPanel;
|
||||
import net.sourceforge.filebot.ui.panel.analyze.tools.SplitPanel;
|
||||
import net.sourceforge.filebot.ui.panel.analyze.tools.ToolPanel;
|
||||
import net.sourceforge.filebot.ui.panel.analyze.tools.TypePanel;
|
||||
|
||||
|
||||
public class AnalyzePanel extends FileBotPanel {
|
||||
|
||||
private FileTreePanel filePanel = new FileTreePanel();
|
||||
private JTabbedPane toolsPanel = new JTabbedPane(SwingConstants.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
|
||||
|
||||
|
||||
public AnalyzePanel() {
|
||||
super("Analyze", ResourceManager.getIcon("panel.analyze"));
|
||||
|
||||
Box panel = new Box(BoxLayout.X_AXIS);
|
||||
|
||||
panel.add(filePanel);
|
||||
|
||||
panel.add(Box.createHorizontalStrut(50));
|
||||
|
||||
JPanel right = new JPanel();
|
||||
right.setLayout(new BorderLayout());
|
||||
right.setBorder(BorderFactory.createTitledBorder("Tools"));
|
||||
|
||||
right.add(toolsPanel, BorderLayout.CENTER);
|
||||
|
||||
panel.add(right);
|
||||
|
||||
add(panel, BorderLayout.CENTER);
|
||||
|
||||
filePanel.getFileTree().addPropertyChangeListener(FileTree.CONTENT_PROPERTY, fileTreeChangeListener);
|
||||
|
||||
addTool(new TypePanel());
|
||||
addTool(new SplitPanel());
|
||||
|
||||
Dimension min = new Dimension(300, 300);
|
||||
filePanel.setMinimumSize(min);
|
||||
toolsPanel.setMinimumSize(min);
|
||||
}
|
||||
|
||||
private PropertyChangeListener fileTreeChangeListener = new PropertyChangeListener() {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
List<File> files = (List<File>) evt.getNewValue();
|
||||
|
||||
for (ToolPanel toolPanel : toolPanels)
|
||||
toolPanel.update(files);
|
||||
}
|
||||
};
|
||||
|
||||
private LinkedList<ToolPanel> toolPanels = new LinkedList<ToolPanel>();
|
||||
|
||||
|
||||
public void addTool(ToolPanel toolPanel) {
|
||||
toolsPanel.addTab(toolPanel.getName(), toolPanel);
|
||||
toolPanels.add(toolPanel);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.analyze;
|
||||
|
||||
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.TreePath;
|
||||
|
||||
import net.sourceforge.filebot.ui.FileBotTree;
|
||||
import net.sourceforge.filebot.ui.sal.FileTransferable;
|
||||
import net.sourceforge.filebot.ui.transferablepolicies.BackgroundFileTransferablePolicy;
|
||||
|
||||
|
||||
public class FileTree extends FileBotTree {
|
||||
|
||||
public static final String LOADING_PROPERTY = "loading";
|
||||
public static final String CONTENT_PROPERTY = "content";
|
||||
|
||||
|
||||
public FileTree() {
|
||||
setTransferablePolicy(new FileTreeTransferPolicy());
|
||||
}
|
||||
|
||||
|
||||
public void removeTreeItems(TreePath paths[]) {
|
||||
for (TreePath element : paths) {
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode) (element.getLastPathComponent());
|
||||
node.removeFromParent();
|
||||
}
|
||||
|
||||
updateUI();
|
||||
|
||||
firePropertyChange(LOADING_PROPERTY, null, true);
|
||||
contentChanged();
|
||||
firePropertyChange(LOADING_PROPERTY, null, false);
|
||||
}
|
||||
|
||||
|
||||
public void load(List<File> files) {
|
||||
FileTransferable tr = new FileTransferable(files);
|
||||
|
||||
if (getTransferablePolicy().accept(tr))
|
||||
getTransferablePolicy().handleTransferable(tr, true);
|
||||
}
|
||||
|
||||
|
||||
private void contentChanged() {
|
||||
List<File> files = convertToList();
|
||||
firePropertyChange(CONTENT_PROPERTY, null, files);
|
||||
}
|
||||
|
||||
|
||||
public void addFiles(DefaultMutableTreeNode parent, File files[]) {
|
||||
// folders first
|
||||
for (File f : files)
|
||||
if (f.isDirectory()) {
|
||||
// run through file tree
|
||||
DefaultMutableTreeNode node = new DefaultMutableTreeNode(f);
|
||||
addFiles(node, f.listFiles());
|
||||
parent.add(node);
|
||||
}
|
||||
|
||||
for (File f : files) {
|
||||
if (!f.isDirectory())
|
||||
parent.add(new DefaultMutableTreeNode(f));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
contentChanged();
|
||||
}
|
||||
|
||||
|
||||
private class FileTreeTransferPolicy extends BackgroundFileTransferablePolicy<Object> implements PropertyChangeListener {
|
||||
|
||||
public FileTreeTransferPolicy() {
|
||||
addPropertyChangeListener(LOADING_PROPERTY, this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean accept(File file) {
|
||||
return file.isFile() || file.isDirectory();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean handleTransferable(Transferable tr, boolean add) {
|
||||
return super.handleTransferable(tr, true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void clear() {
|
||||
FileTree.this.clear();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean load(List<File> files) {
|
||||
DefaultMutableTreeNode root = (DefaultMutableTreeNode) getModel().getRoot();
|
||||
|
||||
File fileArray[] = new File[files.size()];
|
||||
files.toArray(fileArray);
|
||||
|
||||
addFiles(root, fileArray);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method will not be used
|
||||
*/
|
||||
@Override
|
||||
protected boolean load(File file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
Boolean loading = (Boolean) evt.getNewValue();
|
||||
|
||||
if (loading) {
|
||||
FileTree.this.firePropertyChange(LOADING_PROPERTY, null, true);
|
||||
} else {
|
||||
FileTree.this.firePropertyChange(LOADING_PROPERTY, null, false);
|
||||
updateUI();
|
||||
contentChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "files and folders";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.analyze;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import net.sourceforge.filebot.resources.ResourceManager;
|
||||
import net.sourceforge.filebot.ui.FileBotUtil;
|
||||
import net.sourceforge.filebot.ui.sal.LoadAction;
|
||||
import net.sourceforge.tuned.ui.LoadingOverlayPanel;
|
||||
|
||||
|
||||
public class FileTreePanel extends JPanel {
|
||||
|
||||
private FileTree fileTree = new FileTree();
|
||||
|
||||
private LoadingOverlayPanel loadingOverlay;
|
||||
|
||||
|
||||
public FileTreePanel() {
|
||||
super(new BorderLayout());
|
||||
fileTree.addPropertyChangeListener(FileTree.LOADING_PROPERTY, loadingOverlayUpdateListener);
|
||||
|
||||
setBorder(BorderFactory.createTitledBorder("File Tree"));
|
||||
|
||||
loadingOverlay = new LoadingOverlayPanel(new JScrollPane(fileTree), ResourceManager.getIcon("loading"));
|
||||
|
||||
Box buttons = Box.createHorizontalBox();
|
||||
buttons.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
buttons.add(Box.createGlue());
|
||||
buttons.add(new JButton(loadAction));
|
||||
buttons.add(Box.createHorizontalStrut(5));
|
||||
buttons.add(new JButton(clearAction));
|
||||
buttons.add(Box.createGlue());
|
||||
|
||||
// Shortcut DELETE
|
||||
FileBotUtil.registerActionForKeystroke(fileTree, KeyStroke.getKeyStroke("pressed DELETE"), removeAction);
|
||||
|
||||
add(loadingOverlay, BorderLayout.CENTER);
|
||||
add(buttons, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
private PropertyChangeListener loadingOverlayUpdateListener = new PropertyChangeListener() {
|
||||
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
Boolean loading = (Boolean) evt.getNewValue();
|
||||
|
||||
loadingOverlay.setOverlayVisible(loading);
|
||||
loadingOverlay.updateOverlayUI();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public FileTree getFileTree() {
|
||||
return fileTree;
|
||||
}
|
||||
|
||||
private final LoadAction loadAction = new LoadAction(fileTree);
|
||||
|
||||
private final AbstractAction clearAction = new AbstractAction("Clear", ResourceManager.getIcon("action.clear")) {
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
fileTree.clear();
|
||||
}
|
||||
};
|
||||
|
||||
private final AbstractAction removeAction = new AbstractAction("Remove") {
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (fileTree.getSelectionCount() < 1)
|
||||
return;
|
||||
|
||||
int row = fileTree.getMinSelectionRow();
|
||||
|
||||
fileTree.removeTreeItems(fileTree.getSelectionPaths());
|
||||
|
||||
int maxRow = fileTree.getRowCount() - 1;
|
||||
|
||||
if (row > maxRow)
|
||||
row = maxRow;
|
||||
|
||||
fileTree.setSelectionRow(row);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.analyze.tools;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
|
||||
import net.sourceforge.filebot.resources.ResourceManager;
|
||||
import net.sourceforge.filebot.ui.FileBotTree;
|
||||
import net.sourceforge.filebot.ui.FileFormat;
|
||||
import net.sourceforge.tuned.ui.GradientStyle;
|
||||
import net.sourceforge.tuned.ui.LoadingOverlayPanel;
|
||||
import net.sourceforge.tuned.ui.notification.SeparatorBorder;
|
||||
|
||||
|
||||
public class SplitPanel extends ToolPanel implements ChangeListener {
|
||||
|
||||
private FileBotTree tree = new FileBotTree();
|
||||
|
||||
private SpinnerNumberModel spinnerModel = new SpinnerNumberModel(4480, 0, Integer.MAX_VALUE, 100);
|
||||
|
||||
|
||||
public SplitPanel() {
|
||||
super("Split");
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
JScrollPane sp = new JScrollPane(tree);
|
||||
sp.setBorder(BorderFactory.createEmptyBorder());
|
||||
LoadingOverlayPanel loadingOverlay = new LoadingOverlayPanel(sp, ResourceManager.getIcon("loading"));
|
||||
JSpinner spinner = new JSpinner(spinnerModel);
|
||||
spinner.setMaximumSize(spinner.getPreferredSize());
|
||||
spinner.setEditor(new JSpinner.NumberEditor(spinner, "#"));
|
||||
|
||||
Box spinnerBox = Box.createHorizontalBox();
|
||||
spinnerBox.add(Box.createGlue());
|
||||
spinnerBox.add(new JLabel("Split every"));
|
||||
spinnerBox.add(Box.createHorizontalStrut(5));
|
||||
spinnerBox.add(spinner);
|
||||
spinnerBox.add(Box.createHorizontalStrut(5));
|
||||
spinnerBox.add(new JLabel("MB."));
|
||||
spinnerBox.add(Box.createGlue());
|
||||
|
||||
add(loadingOverlay, BorderLayout.CENTER);
|
||||
add(spinnerBox, BorderLayout.SOUTH);
|
||||
|
||||
Color beginColor = new Color(0, 0, 0, 90);
|
||||
SeparatorBorder separatorBorder = new SeparatorBorder(2, beginColor, GradientStyle.TOP_TO_BOTTOM, SeparatorBorder.Position.TOP);
|
||||
spinnerBox.setBorder(new CompoundBorder(separatorBorder, new EmptyBorder(6, 5, 7, 5)));
|
||||
|
||||
setLoadingOverlayPane(loadingOverlay);
|
||||
spinnerModel.addChangeListener(this);
|
||||
spinner.setPreferredSize(new Dimension(80, 20));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* splitsize change callback
|
||||
*/
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
if (files != null)
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
private long getSplitSize() {
|
||||
return spinnerModel.getNumber().intValue() * FileFormat.MEGA;
|
||||
}
|
||||
|
||||
private UpdateTask latestUpdateTask;
|
||||
|
||||
private Collection<File> files;
|
||||
|
||||
|
||||
@Override
|
||||
public void update(Collection<File> files) {
|
||||
this.files = files;
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
private void update() {
|
||||
latestUpdateTask = new UpdateTask();
|
||||
firePropertyChange(LOADING_PROPERTY, null, true);
|
||||
latestUpdateTask.execute();
|
||||
}
|
||||
|
||||
|
||||
private class UpdateTask extends SwingWorker<DefaultTreeModel, Object> {
|
||||
|
||||
private boolean isLatest() {
|
||||
if (this == latestUpdateTask)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private void setLastChildUserObject(DefaultMutableTreeNode root, int part, long size) {
|
||||
DefaultMutableTreeNode node = ((DefaultMutableTreeNode) root.getLastChild());
|
||||
String uo = "Part " + part + " (" + FileFormat.formatSize(size) + ")";
|
||||
node.setUserObject(uo);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected DefaultTreeModel doInBackground() throws Exception {
|
||||
long currentSize = 0;
|
||||
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
|
||||
DefaultMutableTreeNode first = new DefaultMutableTreeNode();
|
||||
root.add(first);
|
||||
DefaultMutableTreeNode remainder = new DefaultMutableTreeNode("Remainder");
|
||||
|
||||
int p = 1;
|
||||
long splitSize = getSplitSize();
|
||||
|
||||
for (File f : files) {
|
||||
long fileSize = f.length();
|
||||
DefaultMutableTreeNode fileNode = new DefaultMutableTreeNode(f);
|
||||
|
||||
if (fileSize > splitSize)
|
||||
remainder.add(fileNode);
|
||||
else if (currentSize + fileSize <= splitSize) {
|
||||
currentSize += fileSize;
|
||||
((DefaultMutableTreeNode) root.getLastChild()).add(fileNode);
|
||||
} else {
|
||||
setLastChildUserObject(root, p, currentSize);
|
||||
|
||||
currentSize = fileSize;
|
||||
p++;
|
||||
DefaultMutableTreeNode node = new DefaultMutableTreeNode();
|
||||
node.add(fileNode);
|
||||
root.add(node);
|
||||
}
|
||||
|
||||
if (!isLatest())
|
||||
return null;
|
||||
}
|
||||
|
||||
setLastChildUserObject(root, p, currentSize);
|
||||
|
||||
if (!remainder.isLeaf())
|
||||
root.add(remainder);
|
||||
|
||||
if (first.isLeaf())
|
||||
first.removeFromParent();
|
||||
|
||||
return new DefaultTreeModel(root);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
DefaultTreeModel model = get();
|
||||
|
||||
if (model == null)
|
||||
return;
|
||||
|
||||
tree.setModel(model);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
SplitPanel.this.firePropertyChange(LOADING_PROPERTY, null, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.analyze.tools;
|
||||
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import net.sourceforge.tuned.ui.LoadingOverlayPanel;
|
||||
|
||||
|
||||
public abstract class ToolPanel extends JComponent {
|
||||
|
||||
private String name = null;
|
||||
|
||||
private LoadingOverlayPanel loadingOverlay;
|
||||
|
||||
public static final String LOADING_PROPERTY = "loading";
|
||||
|
||||
|
||||
public ToolPanel(String name) {
|
||||
this.name = name;
|
||||
addPropertyChangeListener(LOADING_PROPERTY, loadingOverlayUpdateListener);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
protected void setLoadingOverlayPane(LoadingOverlayPanel c) {
|
||||
loadingOverlay = c;
|
||||
}
|
||||
|
||||
private PropertyChangeListener loadingOverlayUpdateListener = new PropertyChangeListener() {
|
||||
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
Boolean loading = (Boolean) evt.getNewValue();
|
||||
|
||||
if (loadingOverlay == null)
|
||||
return;
|
||||
|
||||
loadingOverlay.setOverlayVisible(loading);
|
||||
loadingOverlay.updateOverlayUI();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public abstract void update(Collection<File> list);
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.analyze.tools;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
|
||||
import net.sourceforge.filebot.resources.ResourceManager;
|
||||
import net.sourceforge.filebot.ui.FileBotTree;
|
||||
import net.sourceforge.filebot.ui.FileFormat;
|
||||
import net.sourceforge.tuned.ui.LoadingOverlayPanel;
|
||||
|
||||
|
||||
public class TypePanel extends ToolPanel {
|
||||
|
||||
private FileBotTree tree = new FileBotTree();
|
||||
|
||||
|
||||
public TypePanel() {
|
||||
super("Types");
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
JScrollPane sp = new JScrollPane(tree);
|
||||
sp.setBorder(BorderFactory.createEmptyBorder());
|
||||
LoadingOverlayPanel loadingOverlay = new LoadingOverlayPanel(sp, ResourceManager.getIcon("loading"));
|
||||
add(loadingOverlay, BorderLayout.CENTER);
|
||||
|
||||
setLoadingOverlayPane(loadingOverlay);
|
||||
}
|
||||
|
||||
UpdateTask latestUpdateTask;
|
||||
|
||||
|
||||
@Override
|
||||
public void update(Collection<File> files) {
|
||||
latestUpdateTask = new UpdateTask(files);
|
||||
|
||||
firePropertyChange(LOADING_PROPERTY, null, true);
|
||||
latestUpdateTask.execute();
|
||||
}
|
||||
|
||||
|
||||
private class UpdateTask extends SwingWorker<DefaultTreeModel, Object> {
|
||||
|
||||
private Collection<File> files;
|
||||
|
||||
|
||||
public UpdateTask(Collection<File> files) {
|
||||
this.files = files;
|
||||
}
|
||||
|
||||
|
||||
private boolean isLatest() {
|
||||
if (this == latestUpdateTask)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected DefaultTreeModel doInBackground() throws Exception {
|
||||
TreeMap<String, Collection<File>> map = new TreeMap<String, Collection<File>>();
|
||||
|
||||
for (File f : files) {
|
||||
String suffix = FileFormat.getSuffix(f);
|
||||
|
||||
Collection<File> list = map.get(suffix);
|
||||
|
||||
if (list != null)
|
||||
list.add(f);
|
||||
else {
|
||||
list = new LinkedList<File>();
|
||||
list.add(f);
|
||||
map.put(suffix, list);
|
||||
}
|
||||
|
||||
if (!isLatest())
|
||||
return null;
|
||||
}
|
||||
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
|
||||
Iterator<String> i = map.keySet().iterator();
|
||||
|
||||
while (i.hasNext()) {
|
||||
String key = i.next();
|
||||
Collection<File> list = map.get(key);
|
||||
DefaultMutableTreeNode node = new DefaultMutableTreeNode();
|
||||
long size = 0;
|
||||
|
||||
for (File f : list) {
|
||||
node.add(new DefaultMutableTreeNode(f));
|
||||
size += f.length();
|
||||
}
|
||||
|
||||
node.setUserObject(key + " (" + FileFormat.formatNumberOfFiles(list.size()) + ", " + FileFormat.formatSize(size) + ")");
|
||||
root.add(node);
|
||||
|
||||
if (!isLatest())
|
||||
return null;
|
||||
}
|
||||
|
||||
return new DefaultTreeModel(root);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
DefaultTreeModel model = get();
|
||||
|
||||
if (model == null)
|
||||
return;
|
||||
|
||||
tree.setModel(model);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
TypePanel.this.firePropertyChange(LOADING_PROPERTY, null, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.create;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
|
||||
import javax.swing.Box;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import net.sourceforge.filebot.ui.FileBotList;
|
||||
import net.sourceforge.filebot.ui.sal.SaveAction;
|
||||
|
||||
|
||||
public class CreateList extends FileBotList {
|
||||
|
||||
private SaveAction saveAction = new SaveAction(this);
|
||||
|
||||
|
||||
public CreateList() {
|
||||
super(false, true, true);
|
||||
|
||||
setTitle("List");
|
||||
|
||||
Box buttons = Box.createHorizontalBox();
|
||||
buttons.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
buttons.add(Box.createGlue());
|
||||
buttons.add(new JButton(saveAction));
|
||||
buttons.add(Box.createGlue());
|
||||
|
||||
add(buttons, BorderLayout.SOUTH);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.create;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.text.NumberFormat;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import net.sourceforge.filebot.resources.ResourceManager;
|
||||
import net.sourceforge.filebot.ui.FileBotPanel;
|
||||
import net.sourceforge.filebot.ui.FileBotUtil;
|
||||
|
||||
|
||||
public class CreatePanel extends FileBotPanel {
|
||||
|
||||
private SpinnerNumberModel fromSpinnerModel = new SpinnerNumberModel(1, 1, Integer.MAX_VALUE, 1);
|
||||
private SpinnerNumberModel toSpinnerModel = new SpinnerNumberModel(20, 1, Integer.MAX_VALUE, 1);
|
||||
|
||||
private CreateList list = new CreateList();
|
||||
|
||||
private JTextField textField = new JTextField("Name - $i", 25);
|
||||
|
||||
|
||||
public CreatePanel() {
|
||||
super("Create", ResourceManager.getIcon("panel.create"));
|
||||
|
||||
JSpinner fromSpinner = new JSpinner(fromSpinnerModel);
|
||||
JSpinner toSpinner = new JSpinner(toSpinnerModel);
|
||||
|
||||
fromSpinner.setEditor(new JSpinner.NumberEditor(fromSpinner, "#"));
|
||||
toSpinner.setEditor(new JSpinner.NumberEditor(toSpinner, "#"));
|
||||
|
||||
Dimension spinnerDimension = new Dimension(50, textField.getPreferredSize().height);
|
||||
fromSpinner.setPreferredSize(spinnerDimension);
|
||||
toSpinner.setPreferredSize(spinnerDimension);
|
||||
|
||||
Box spinners = Box.createHorizontalBox();
|
||||
spinners.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
spinners.add(Box.createHorizontalGlue());
|
||||
|
||||
spinners.add(createLabeledComponent("Pattern:", textField));
|
||||
spinners.add(Box.createHorizontalStrut(15));
|
||||
spinners.add(createLabeledComponent("From:", fromSpinner));
|
||||
spinners.add(Box.createHorizontalStrut(10));
|
||||
spinners.add(createLabeledComponent("To:", toSpinner));
|
||||
spinners.add(Box.createHorizontalStrut(15));
|
||||
spinners.add(new JButton(createAction));
|
||||
spinners.add(Box.createHorizontalGlue());
|
||||
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
|
||||
panel.add(spinners, BorderLayout.NORTH);
|
||||
panel.add(list, BorderLayout.CENTER);
|
||||
|
||||
add(panel, BorderLayout.CENTER);
|
||||
|
||||
FileBotUtil.registerActionForKeystroke(this, KeyStroke.getKeyStroke("ENTER"), createAction);
|
||||
}
|
||||
|
||||
|
||||
private JComponent createLabeledComponent(String label, JComponent component) {
|
||||
Box box = Box.createHorizontalBox();
|
||||
box.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
box.add(new JLabel(label));
|
||||
box.add(Box.createHorizontalStrut(6));
|
||||
box.add(component);
|
||||
|
||||
box.setMaximumSize(box.getPreferredSize());
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
private AbstractAction createAction = new AbstractAction("Create") {
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
list.getModel().clear();
|
||||
|
||||
int from = fromSpinnerModel.getNumber().intValue();
|
||||
int to = toSpinnerModel.getNumber().intValue();
|
||||
|
||||
NumberFormat format = NumberFormat.getInstance();
|
||||
format.setGroupingUsed(false);
|
||||
|
||||
format.setMinimumIntegerDigits(Math.max(Integer.toString(to).length(), 2));
|
||||
|
||||
String pattern = textField.getText();
|
||||
|
||||
for (int i = from; i <= to; i++) {
|
||||
String s = pattern.replaceAll("\\$i", format.format(i));
|
||||
list.getModel().addElement(s);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.list;
|
||||
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
|
||||
import javax.swing.Box;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import net.sourceforge.filebot.ui.FileBotList;
|
||||
import net.sourceforge.filebot.ui.sal.LoadAction;
|
||||
import net.sourceforge.filebot.ui.sal.SaveAction;
|
||||
|
||||
|
||||
public class FileList extends FileBotList {
|
||||
|
||||
private SaveAction saveAction = new SaveAction(this);
|
||||
|
||||
private LoadAction loadAction = new LoadAction(this);
|
||||
|
||||
|
||||
public FileList() {
|
||||
super(true, true, true);
|
||||
|
||||
setTransferablePolicy(new FileListTransferablePolicy(this));
|
||||
|
||||
setTitle("Folder");
|
||||
|
||||
Box buttons = Box.createHorizontalBox();
|
||||
buttons.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
buttons.add(Box.createHorizontalGlue());
|
||||
|
||||
buttons.add(new JButton(loadAction));
|
||||
buttons.add(Box.createHorizontalStrut(5));
|
||||
buttons.add(new JButton(saveAction));
|
||||
buttons.add(Box.createHorizontalGlue());
|
||||
|
||||
add(buttons, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
}
|