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