diff --git a/BuildData.groovy b/BuildData.groovy index 46354c48..7e76a195 100644 --- a/BuildData.groovy +++ b/BuildData.groovy @@ -187,7 +187,7 @@ tvdb_updates.each{ update -> def imdb_name = _guarded{ if (imdbid =~ /tt(\d+)/) { def dom = IMDb.parsePage(IMDb.getMoviePageLink(imdbid.match(/tt(\d+)/) as int).toURL()) - return net.sourceforge.tuned.XPathUtilities.selectString("//META[@property='og:title']/@content", dom) + return net.sourceforge.filebot.util.XPathUtilities.selectString("//META[@property='og:title']/@content", dom) } } def data = [update.time, update.id, imdbid, tvdb_name ?: '', imdb_name ?: '', rating ?: 0, votes ?: 0] diff --git a/installer/portable/FileBot.l4j.ini b/installer/portable/FileBot.l4j.ini index fc12a05b..3375f603 100644 --- a/installer/portable/FileBot.l4j.ini +++ b/installer/portable/FileBot.l4j.ini @@ -33,7 +33,7 @@ -Dnet.sourceforge.filebot.AcoustID.fpcalc="%EXEDIR%\fpcalc.exe" # store preferences to text file --Djava.util.prefs.PreferencesFactory=net.sourceforge.tuned.prefs.FilePreferencesFactory +-Djava.util.prefs.PreferencesFactory=net.sourceforge.filebot.util.prefs.FilePreferencesFactory -Dnet.sourceforge.tuned.prefs.file="%EXEDIR%\prefs.properties" # boost application startup speed diff --git a/installer/portable/filebot.cmd b/installer/portable/filebot.cmd index 32f7c66b..c1178c91 100644 --- a/installer/portable/filebot.cmd +++ b/installer/portable/filebot.cmd @@ -1,2 +1,2 @@ @ECHO OFF -java -XX:+TieredCompilation -Dunixfs=false -DuseExtendedFileAttributes=false -DuseCreationDate=false -Djava.net.useSystemProxies=false -Dsun.net.client.defaultConnectTimeout=10000 -Dsun.net.client.defaultReadTimeout=60000 -Djna.nosys=true -Dapplication.deployment=portable -Dapplication.analytics=true "-Dapplication.dir=%~dp0." "-Duser.home=%~dp0." "-Djava.io.tmpdir=%~dp0temp" "-Djna.library.path=%~dp0" "-Djava.library.path=%~dp0" -Dnet.sourceforge.filebot.AcoustID.fpcalc="%~dp0fpcalc.exe" -Djava.util.prefs.PreferencesFactory=net.sourceforge.tuned.prefs.FilePreferencesFactory "-Dnet.sourceforge.tuned.prefs.file=%~dp0prefs.properties" -jar "%~dp0FileBot.jar" %* \ No newline at end of file +java -XX:+TieredCompilation -Dunixfs=false -DuseExtendedFileAttributes=false -DuseCreationDate=false -Djava.net.useSystemProxies=false -Dsun.net.client.defaultConnectTimeout=10000 -Dsun.net.client.defaultReadTimeout=60000 -Djna.nosys=true -Dapplication.deployment=portable -Dapplication.analytics=true "-Dapplication.dir=%~dp0." "-Duser.home=%~dp0." "-Djava.io.tmpdir=%~dp0temp" "-Djna.library.path=%~dp0" "-Djava.library.path=%~dp0" -Dnet.sourceforge.filebot.AcoustID.fpcalc="%~dp0fpcalc.exe" -Djava.util.prefs.PreferencesFactory=net.sourceforge.filebot.util.prefs.FilePreferencesFactory "-Dnet.sourceforge.tuned.prefs.file=%~dp0prefs.properties" -jar "%~dp0FileBot.jar" %* \ No newline at end of file diff --git a/installer/portable/filebot.sh b/installer/portable/filebot.sh index e57dfbdd..141b42a3 100644 --- a/installer/portable/filebot.sh +++ b/installer/portable/filebot.sh @@ -6,4 +6,4 @@ dir_bin="$( cd -P "$( dirname "$SOURCE" )" && pwd )" # force JVM language and encoding settings export LANG=en_US.utf8 -java -Dunixfs=false -DuseGVFS=false -DuseExtendedFileAttributes=false -DuseCreationDate=false -Dfile.encoding=UTF-8 -Djava.net.useSystemProxies=false -Dsun.net.client.defaultConnectTimeout=10000 -Dsun.net.client.defaultReadTimeout=60000 -Djna.nosys=true -Dapplication.deployment=portable -Dapplication.analytics=true -Dapplication.warmup=false -Dnet.sourceforge.filebot.AcoustID.fpcalc=fpcalc "-Dapplication.dir=$dir_bin" "-Djava.io.tmpdir=$dir_bin/temp" "-Duser.home=$dir_bin" "-Djna.library.path=$dir_bin" "-Djava.library.path=$dir_bin" -Djava.util.prefs.PreferencesFactory=net.sourceforge.tuned.prefs.FilePreferencesFactory "-Dnet.sourceforge.tuned.prefs.file=$dir_bin/prefs.properties" -jar "$dir_bin/FileBot.jar" "$@" +java -Dunixfs=false -DuseGVFS=false -DuseExtendedFileAttributes=false -DuseCreationDate=false -Dfile.encoding=UTF-8 -Djava.net.useSystemProxies=false -Dsun.net.client.defaultConnectTimeout=10000 -Dsun.net.client.defaultReadTimeout=60000 -Djna.nosys=true -Dapplication.deployment=portable -Dapplication.analytics=true -Dapplication.warmup=false -Dnet.sourceforge.filebot.AcoustID.fpcalc=fpcalc "-Dapplication.dir=$dir_bin" "-Djava.io.tmpdir=$dir_bin/temp" "-Duser.home=$dir_bin" "-Djna.library.path=$dir_bin" "-Djava.library.path=$dir_bin" -Djava.util.prefs.PreferencesFactory=net.sourceforge.filebot.util.prefs.FilePreferencesFactory "-Dnet.sourceforge.tuned.prefs.file=$dir_bin/prefs.properties" -jar "$dir_bin/FileBot.jar" "$@" diff --git a/source/net/sourceforge/filebot/Main.java b/source/net/sourceforge/filebot/Main.java index de03cb32..8d4d4f9a 100644 --- a/source/net/sourceforge/filebot/Main.java +++ b/source/net/sourceforge/filebot/Main.java @@ -4,8 +4,8 @@ import static java.awt.GraphicsEnvironment.*; import static java.util.regex.Pattern.*; import static javax.swing.JOptionPane.*; import static net.sourceforge.filebot.Settings.*; -import static net.sourceforge.tuned.FileUtilities.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Desktop; import java.awt.Dialog.ModalityType; @@ -59,9 +59,9 @@ import net.sourceforge.filebot.ui.MainFrame; import net.sourceforge.filebot.ui.PanelBuilder; import net.sourceforge.filebot.ui.SinglePanelFrame; import net.sourceforge.filebot.web.CachedResource; -import net.sourceforge.tuned.ByteBufferInputStream; -import net.sourceforge.tuned.PreferencesMap.PreferencesEntry; -import net.sourceforge.tuned.TeePrintStream; +import net.sourceforge.filebot.util.ByteBufferInputStream; +import net.sourceforge.filebot.util.PreferencesMap.PreferencesEntry; +import net.sourceforge.filebot.util.TeePrintStream; import org.w3c.dom.NodeList; diff --git a/source/net/sourceforge/filebot/MediaTypes.java b/source/net/sourceforge/filebot/MediaTypes.java index f9618844..5854c35f 100644 --- a/source/net/sourceforge/filebot/MediaTypes.java +++ b/source/net/sourceforge/filebot/MediaTypes.java @@ -1,7 +1,7 @@ package net.sourceforge.filebot; import static java.util.Collections.*; -import static net.sourceforge.tuned.XPathUtilities.*; +import static net.sourceforge.filebot.util.XPathUtilities.*; import java.util.ArrayList; import java.util.HashMap; @@ -11,7 +11,7 @@ import java.util.Map.Entry; import javax.xml.parsers.DocumentBuilderFactory; -import net.sourceforge.tuned.FileUtilities.ExtensionFileFilter; +import net.sourceforge.filebot.util.FileUtilities.ExtensionFileFilter; import org.w3c.dom.Document; import org.w3c.dom.Node; diff --git a/source/net/sourceforge/filebot/NativeRenameAction.java b/source/net/sourceforge/filebot/NativeRenameAction.java index e7684c86..8d53c1da 100644 --- a/source/net/sourceforge/filebot/NativeRenameAction.java +++ b/source/net/sourceforge/filebot/NativeRenameAction.java @@ -3,7 +3,7 @@ package net.sourceforge.filebot; import static java.util.Collections.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; import java.io.IOException; diff --git a/source/net/sourceforge/filebot/Settings.java b/source/net/sourceforge/filebot/Settings.java index 97babbff..a2e06868 100644 --- a/source/net/sourceforge/filebot/Settings.java +++ b/source/net/sourceforge/filebot/Settings.java @@ -1,6 +1,6 @@ package net.sourceforge.filebot; -import static net.sourceforge.tuned.StringUtilities.*; +import static net.sourceforge.filebot.util.StringUtilities.*; import java.awt.GraphicsEnvironment; import java.io.File; @@ -9,11 +9,11 @@ import java.util.ResourceBundle; import java.util.prefs.BackingStoreException; import java.util.prefs.Preferences; -import net.sourceforge.tuned.ExceptionUtilities; -import net.sourceforge.tuned.PreferencesList; -import net.sourceforge.tuned.PreferencesMap; -import net.sourceforge.tuned.PreferencesMap.PreferencesEntry; -import net.sourceforge.tuned.PreferencesMap.StringAdapter; +import net.sourceforge.filebot.util.ExceptionUtilities; +import net.sourceforge.filebot.util.PreferencesList; +import net.sourceforge.filebot.util.PreferencesMap; +import net.sourceforge.filebot.util.PreferencesMap.PreferencesEntry; +import net.sourceforge.filebot.util.PreferencesMap.StringAdapter; public final class Settings { diff --git a/source/net/sourceforge/filebot/StandardRenameAction.java b/source/net/sourceforge/filebot/StandardRenameAction.java index 35e277b7..b3d116c7 100644 --- a/source/net/sourceforge/filebot/StandardRenameAction.java +++ b/source/net/sourceforge/filebot/StandardRenameAction.java @@ -3,7 +3,7 @@ package net.sourceforge.filebot; import java.io.File; import java.io.IOException; -import net.sourceforge.tuned.FileUtilities; +import net.sourceforge.filebot.util.FileUtilities; public enum StandardRenameAction implements RenameAction { diff --git a/source/net/sourceforge/filebot/archive/Archive.java b/source/net/sourceforge/filebot/archive/Archive.java index 53b45b37..a2641f7d 100644 --- a/source/net/sourceforge/filebot/archive/Archive.java +++ b/source/net/sourceforge/filebot/archive/Archive.java @@ -23,7 +23,7 @@ import net.sf.sevenzipjbinding.SevenZipException; import net.sourceforge.filebot.MediaTypes; import net.sourceforge.filebot.vfs.FileInfo; import net.sourceforge.filebot.vfs.SimpleFileInfo; -import net.sourceforge.tuned.FileUtilities.ExtensionFileFilter; +import net.sourceforge.filebot.util.FileUtilities.ExtensionFileFilter; public class Archive implements Closeable { diff --git a/source/net/sourceforge/filebot/cli/ArgumentBean.java b/source/net/sourceforge/filebot/cli/ArgumentBean.java index 699d2d5e..9eff6bac 100644 --- a/source/net/sourceforge/filebot/cli/ArgumentBean.java +++ b/source/net/sourceforge/filebot/cli/ArgumentBean.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.cli; import static java.util.Arrays.*; import static java.util.Collections.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; import java.util.ArrayList; diff --git a/source/net/sourceforge/filebot/cli/ArgumentProcessor.java b/source/net/sourceforge/filebot/cli/ArgumentProcessor.java index d4e486f0..c1e61d20 100644 --- a/source/net/sourceforge/filebot/cli/ArgumentProcessor.java +++ b/source/net/sourceforge/filebot/cli/ArgumentProcessor.java @@ -2,8 +2,8 @@ package net.sourceforge.filebot.cli; import static net.sourceforge.filebot.Settings.*; import static net.sourceforge.filebot.cli.CLILogging.*; -import static net.sourceforge.tuned.ExceptionUtilities.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.ExceptionUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; import java.io.FileInputStream; diff --git a/source/net/sourceforge/filebot/cli/CmdlineOperations.java b/source/net/sourceforge/filebot/cli/CmdlineOperations.java index ab8c4c3a..81214f3f 100644 --- a/source/net/sourceforge/filebot/cli/CmdlineOperations.java +++ b/source/net/sourceforge/filebot/cli/CmdlineOperations.java @@ -10,7 +10,7 @@ import static net.sourceforge.filebot.cli.CLILogging.*; import static net.sourceforge.filebot.hash.VerificationUtilities.*; import static net.sourceforge.filebot.media.MediaDetection.*; import static net.sourceforge.filebot.subtitle.SubtitleUtilities.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; import java.io.FileFilter; @@ -75,7 +75,7 @@ import net.sourceforge.filebot.web.SortOrder; import net.sourceforge.filebot.web.SubtitleDescriptor; import net.sourceforge.filebot.web.SubtitleProvider; import net.sourceforge.filebot.web.VideoHashSubtitleService; -import net.sourceforge.tuned.FileUtilities.ParentFilter; +import net.sourceforge.filebot.util.FileUtilities.ParentFilter; public class CmdlineOperations implements CmdlineInterface { diff --git a/source/net/sourceforge/filebot/cli/FolderWatchService.java b/source/net/sourceforge/filebot/cli/FolderWatchService.java index e1c568c7..450efeba 100644 --- a/source/net/sourceforge/filebot/cli/FolderWatchService.java +++ b/source/net/sourceforge/filebot/cli/FolderWatchService.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.cli; import static java.nio.file.StandardWatchEventKinds.*; import static java.util.Collections.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.Closeable; import java.io.File; @@ -24,8 +24,8 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; -import net.sourceforge.tuned.DefaultThreadFactory; -import net.sourceforge.tuned.Timer; +import net.sourceforge.filebot.util.DefaultThreadFactory; +import net.sourceforge.filebot.util.Timer; public abstract class FolderWatchService implements Closeable { diff --git a/source/net/sourceforge/filebot/cli/GroovyPad.java b/source/net/sourceforge/filebot/cli/GroovyPad.java index d8b36b93..70f5a94b 100644 --- a/source/net/sourceforge/filebot/cli/GroovyPad.java +++ b/source/net/sourceforge/filebot/cli/GroovyPad.java @@ -1,6 +1,6 @@ package net.sourceforge.filebot.cli; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.BorderLayout; import java.awt.Color; @@ -39,7 +39,7 @@ import net.sourceforge.filebot.Analytics; import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.Settings; import net.sourceforge.filebot.cli.ArgumentProcessor.DefaultScriptProvider; -import net.sourceforge.tuned.TeePrintStream; +import net.sourceforge.filebot.util.TeePrintStream; import org.fife.ui.rsyntaxtextarea.FileLocation; import org.fife.ui.rsyntaxtextarea.SyntaxConstants; diff --git a/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy b/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy index 426849eb..7eff365c 100644 --- a/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy +++ b/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy @@ -36,7 +36,7 @@ List.metaClass.eachMediaFolder = { c -> delegate.findResults{ it.getMediaFolders // File utility methods -import static net.sourceforge.tuned.FileUtilities.* +import static net.sourceforge.filebot.util.FileUtilities.* File.metaClass.getNameWithoutExtension = { getNameWithoutExtension(delegate.getName()) } File.metaClass.getPathWithoutExtension = { new File(delegate.getParentFile(), getNameWithoutExtension(delegate.getName())).getPath() } diff --git a/source/net/sourceforge/filebot/format/ExpressionBindings.java b/source/net/sourceforge/filebot/format/ExpressionBindings.java index 96c63809..6a3b3f57 100644 --- a/source/net/sourceforge/filebot/format/ExpressionBindings.java +++ b/source/net/sourceforge/filebot/format/ExpressionBindings.java @@ -9,7 +9,7 @@ import java.util.TreeMap; import javax.script.Bindings; -import net.sourceforge.tuned.ExceptionUtilities; +import net.sourceforge.filebot.util.ExceptionUtilities; public class ExpressionBindings extends AbstractMap implements Bindings { diff --git a/source/net/sourceforge/filebot/format/ExpressionFormat.java b/source/net/sourceforge/filebot/format/ExpressionFormat.java index 3ee58e19..f1ab12f5 100644 --- a/source/net/sourceforge/filebot/format/ExpressionFormat.java +++ b/source/net/sourceforge/filebot/format/ExpressionFormat.java @@ -2,8 +2,8 @@ package net.sourceforge.filebot.format; -import static net.sourceforge.tuned.ExceptionUtilities.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.ExceptionUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import groovy.lang.GroovyRuntimeException; import groovy.lang.MissingPropertyException; diff --git a/source/net/sourceforge/filebot/format/ExpressionFormat.lib.groovy b/source/net/sourceforge/filebot/format/ExpressionFormat.lib.groovy index 80e4d950..ef5f523e 100644 --- a/source/net/sourceforge/filebot/format/ExpressionFormat.lib.groovy +++ b/source/net/sourceforge/filebot/format/ExpressionFormat.lib.groovy @@ -1,5 +1,5 @@ -import static net.sourceforge.tuned.FileUtilities.* +import static net.sourceforge.filebot.util.FileUtilities.* import java.util.regex.Pattern @@ -240,8 +240,8 @@ Object.metaClass.match = { Map cases -> * Web and File IO helpers */ import net.sourceforge.filebot.web.WebRequest -import net.sourceforge.tuned.FileUtilities -import net.sourceforge.tuned.XPathUtilities +import net.sourceforge.filebot.util.FileUtilities +import net.sourceforge.filebot.util.XPathUtilities URL.metaClass.getText = { FileUtilities.readAll(WebRequest.getReader(delegate.openConnection())) } URL.metaClass.getHtml = { new XmlParser(new org.cyberneko.html.parsers.SAXParser()).parseText(delegate.getText()) } diff --git a/source/net/sourceforge/filebot/format/MediaBindingBean.java b/source/net/sourceforge/filebot/format/MediaBindingBean.java index 30e617ae..6c676ab7 100644 --- a/source/net/sourceforge/filebot/format/MediaBindingBean.java +++ b/source/net/sourceforge/filebot/format/MediaBindingBean.java @@ -8,8 +8,8 @@ import static net.sourceforge.filebot.hash.VerificationUtilities.*; import static net.sourceforge.filebot.media.MediaDetection.*; import static net.sourceforge.filebot.similarity.Normalization.*; import static net.sourceforge.filebot.web.EpisodeFormat.*; -import static net.sourceforge.tuned.FileUtilities.*; -import static net.sourceforge.tuned.StringUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; +import static net.sourceforge.filebot.util.StringUtilities.*; import java.io.File; import java.io.IOException; @@ -47,8 +47,8 @@ import net.sourceforge.filebot.web.MultiEpisode; import net.sourceforge.filebot.web.SearchResult; import net.sourceforge.filebot.web.SortOrder; import net.sourceforge.filebot.web.TheTVDBSearchResult; -import net.sourceforge.tuned.FileUtilities; -import net.sourceforge.tuned.FileUtilities.ExtensionFileFilter; +import net.sourceforge.filebot.util.FileUtilities; +import net.sourceforge.filebot.util.FileUtilities.ExtensionFileFilter; import com.cedarsoftware.util.io.JsonWriter; diff --git a/source/net/sourceforge/filebot/format/SecureCompiledScript.java b/source/net/sourceforge/filebot/format/SecureCompiledScript.java index 198c3ed8..4d894a3c 100644 --- a/source/net/sourceforge/filebot/format/SecureCompiledScript.java +++ b/source/net/sourceforge/filebot/format/SecureCompiledScript.java @@ -19,7 +19,7 @@ import javax.script.ScriptContext; import javax.script.ScriptEngine; import javax.script.ScriptException; -import net.sourceforge.tuned.ExceptionUtilities; +import net.sourceforge.filebot.util.ExceptionUtilities; public class SecureCompiledScript extends CompiledScript { diff --git a/source/net/sourceforge/filebot/hash/HashType.java b/source/net/sourceforge/filebot/hash/HashType.java index 0de0c005..518f5bdc 100644 --- a/source/net/sourceforge/filebot/hash/HashType.java +++ b/source/net/sourceforge/filebot/hash/HashType.java @@ -5,7 +5,7 @@ package net.sourceforge.filebot.hash; import java.util.zip.CRC32; import net.sourceforge.filebot.MediaTypes; -import net.sourceforge.tuned.FileUtilities.ExtensionFileFilter; +import net.sourceforge.filebot.util.FileUtilities.ExtensionFileFilter; public enum HashType { diff --git a/source/net/sourceforge/filebot/hash/VerificationUtilities.java b/source/net/sourceforge/filebot/hash/VerificationUtilities.java index 5c4bf0e4..b00da860 100644 --- a/source/net/sourceforge/filebot/hash/VerificationUtilities.java +++ b/source/net/sourceforge/filebot/hash/VerificationUtilities.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.hash; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; import java.io.FileInputStream; diff --git a/source/net/sourceforge/filebot/media/MediaDetection.java b/source/net/sourceforge/filebot/media/MediaDetection.java index d4287083..7208cbe9 100644 --- a/source/net/sourceforge/filebot/media/MediaDetection.java +++ b/source/net/sourceforge/filebot/media/MediaDetection.java @@ -6,7 +6,7 @@ import static net.sourceforge.filebot.MediaTypes.*; import static net.sourceforge.filebot.Settings.*; import static net.sourceforge.filebot.similarity.CommonSequenceMatcher.*; import static net.sourceforge.filebot.similarity.Normalization.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; import java.io.FileFilter; diff --git a/source/net/sourceforge/filebot/media/ReleaseInfo.java b/source/net/sourceforge/filebot/media/ReleaseInfo.java index f343c8e8..cd9d960b 100644 --- a/source/net/sourceforge/filebot/media/ReleaseInfo.java +++ b/source/net/sourceforge/filebot/media/ReleaseInfo.java @@ -6,8 +6,8 @@ import static java.util.Collections.*; import static java.util.ResourceBundle.*; import static java.util.regex.Pattern.*; import static net.sourceforge.filebot.similarity.Normalization.*; -import static net.sourceforge.tuned.FileUtilities.*; -import static net.sourceforge.tuned.StringUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; +import static net.sourceforge.filebot.util.StringUtilities.*; import java.io.File; import java.io.FileFilter; @@ -35,8 +35,8 @@ import net.sourceforge.filebot.web.AnidbSearchResult; import net.sourceforge.filebot.web.CachedResource; import net.sourceforge.filebot.web.Movie; import net.sourceforge.filebot.web.TheTVDBSearchResult; -import net.sourceforge.tuned.ByteBufferInputStream; -import net.sourceforge.tuned.FileUtilities.RegexFileFilter; +import net.sourceforge.filebot.util.ByteBufferInputStream; +import net.sourceforge.filebot.util.FileUtilities.RegexFileFilter; import org.tukaani.xz.XZInputStream; diff --git a/source/net/sourceforge/filebot/similarity/EpisodeMetrics.java b/source/net/sourceforge/filebot/similarity/EpisodeMetrics.java index 10605950..a8a6cff0 100644 --- a/source/net/sourceforge/filebot/similarity/EpisodeMetrics.java +++ b/source/net/sourceforge/filebot/similarity/EpisodeMetrics.java @@ -5,8 +5,8 @@ import static java.util.Collections.*; import static java.util.regex.Pattern.*; import static net.sourceforge.filebot.Settings.*; import static net.sourceforge.filebot.similarity.Normalization.*; -import static net.sourceforge.tuned.FileUtilities.*; -import static net.sourceforge.tuned.StringUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; +import static net.sourceforge.filebot.util.StringUtilities.*; import java.io.File; import java.io.IOException; diff --git a/source/net/sourceforge/filebot/similarity/FileNameMetric.java b/source/net/sourceforge/filebot/similarity/FileNameMetric.java index fd1ae0d1..55e2ab96 100644 --- a/source/net/sourceforge/filebot/similarity/FileNameMetric.java +++ b/source/net/sourceforge/filebot/similarity/FileNameMetric.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.similarity; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; diff --git a/source/net/sourceforge/filebot/similarity/SeasonEpisodeMatcher.java b/source/net/sourceforge/filebot/similarity/SeasonEpisodeMatcher.java index ff61fa99..31844a81 100644 --- a/source/net/sourceforge/filebot/similarity/SeasonEpisodeMatcher.java +++ b/source/net/sourceforge/filebot/similarity/SeasonEpisodeMatcher.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.similarity; import static java.util.Collections.*; import static java.util.regex.Pattern.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; import java.util.ArrayList; diff --git a/source/net/sourceforge/filebot/similarity/SeriesNameMatcher.java b/source/net/sourceforge/filebot/similarity/SeriesNameMatcher.java index 7414b700..a38373e2 100644 --- a/source/net/sourceforge/filebot/similarity/SeriesNameMatcher.java +++ b/source/net/sourceforge/filebot/similarity/SeriesNameMatcher.java @@ -4,7 +4,7 @@ import static java.util.Collections.*; import static java.util.regex.Pattern.*; import static net.sourceforge.filebot.similarity.CommonSequenceMatcher.*; import static net.sourceforge.filebot.similarity.Normalization.*; -import static net.sourceforge.tuned.StringUtilities.*; +import static net.sourceforge.filebot.util.StringUtilities.*; import java.io.File; import java.text.CollationKey; @@ -25,7 +25,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import net.sourceforge.filebot.similarity.SeasonEpisodeMatcher.SxE; -import net.sourceforge.tuned.FileUtilities; +import net.sourceforge.filebot.util.FileUtilities; public class SeriesNameMatcher { diff --git a/source/net/sourceforge/filebot/subtitle/MicroDVDReader.java b/source/net/sourceforge/filebot/subtitle/MicroDVDReader.java index 502c2c1c..bc139bd7 100644 --- a/source/net/sourceforge/filebot/subtitle/MicroDVDReader.java +++ b/source/net/sourceforge/filebot/subtitle/MicroDVDReader.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.subtitle; -import static net.sourceforge.tuned.StringUtilities.*; +import static net.sourceforge.filebot.util.StringUtilities.*; import java.util.ArrayList; import java.util.List; diff --git a/source/net/sourceforge/filebot/subtitle/SubRipReader.java b/source/net/sourceforge/filebot/subtitle/SubRipReader.java index 1f8d7467..6af5d2e1 100644 --- a/source/net/sourceforge/filebot/subtitle/SubRipReader.java +++ b/source/net/sourceforge/filebot/subtitle/SubRipReader.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.subtitle; -import static net.sourceforge.tuned.StringUtilities.*; +import static net.sourceforge.filebot.util.StringUtilities.*; import java.text.DateFormat; import java.text.SimpleDateFormat; diff --git a/source/net/sourceforge/filebot/subtitle/SubViewerReader.java b/source/net/sourceforge/filebot/subtitle/SubViewerReader.java index a22b5a04..f61e5172 100644 --- a/source/net/sourceforge/filebot/subtitle/SubViewerReader.java +++ b/source/net/sourceforge/filebot/subtitle/SubViewerReader.java @@ -3,7 +3,7 @@ package net.sourceforge.filebot.subtitle; import static java.util.regex.Pattern.*; -import static net.sourceforge.tuned.StringUtilities.*; +import static net.sourceforge.filebot.util.StringUtilities.*; import java.text.DateFormat; import java.text.ParseException; diff --git a/source/net/sourceforge/filebot/subtitle/SubtitleFormat.java b/source/net/sourceforge/filebot/subtitle/SubtitleFormat.java index a84c2ceb..72408827 100644 --- a/source/net/sourceforge/filebot/subtitle/SubtitleFormat.java +++ b/source/net/sourceforge/filebot/subtitle/SubtitleFormat.java @@ -3,7 +3,7 @@ package net.sourceforge.filebot.subtitle; import net.sourceforge.filebot.MediaTypes; -import net.sourceforge.tuned.FileUtilities.ExtensionFileFilter; +import net.sourceforge.filebot.util.FileUtilities.ExtensionFileFilter; public enum SubtitleFormat { diff --git a/source/net/sourceforge/filebot/subtitle/SubtitleNaming.java b/source/net/sourceforge/filebot/subtitle/SubtitleNaming.java index 1fc8e9a8..e06f3eb2 100644 --- a/source/net/sourceforge/filebot/subtitle/SubtitleNaming.java +++ b/source/net/sourceforge/filebot/subtitle/SubtitleNaming.java @@ -1,6 +1,6 @@ package net.sourceforge.filebot.subtitle; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; diff --git a/source/net/sourceforge/filebot/subtitle/SubtitleUtilities.java b/source/net/sourceforge/filebot/subtitle/SubtitleUtilities.java index 590b6f38..7435b1a8 100644 --- a/source/net/sourceforge/filebot/subtitle/SubtitleUtilities.java +++ b/source/net/sourceforge/filebot/subtitle/SubtitleUtilities.java @@ -6,7 +6,7 @@ import static net.sourceforge.filebot.MediaTypes.*; import static net.sourceforge.filebot.media.MediaDetection.*; import static net.sourceforge.filebot.similarity.EpisodeMetrics.*; import static net.sourceforge.filebot.similarity.Normalization.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; import java.io.IOException; diff --git a/source/net/sourceforge/filebot/ui/AbstractSearchPanel.java b/source/net/sourceforge/filebot/ui/AbstractSearchPanel.java index 34507f66..c3a069df 100644 --- a/source/net/sourceforge/filebot/ui/AbstractSearchPanel.java +++ b/source/net/sourceforge/filebot/ui/AbstractSearchPanel.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.ui; import static javax.swing.ScrollPaneConstants.*; import static net.sourceforge.filebot.ui.NotificationLogging.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Dimension; import java.awt.Window; @@ -35,9 +35,9 @@ import net.miginfocom.swing.MigLayout; import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.Settings; import net.sourceforge.filebot.web.SearchResult; -import net.sourceforge.tuned.ExceptionUtilities; -import net.sourceforge.tuned.ui.LabelProvider; -import net.sourceforge.tuned.ui.SelectButton; +import net.sourceforge.filebot.util.ExceptionUtilities; +import net.sourceforge.filebot.util.ui.LabelProvider; +import net.sourceforge.filebot.util.ui.SelectButton; import ca.odell.glazedlists.BasicEventList; import ca.odell.glazedlists.matchers.TextMatcherEditor; import ca.odell.glazedlists.swing.AutoCompleteSupport; diff --git a/source/net/sourceforge/filebot/ui/FileBotList.java b/source/net/sourceforge/filebot/ui/FileBotList.java index 314eb153..0d9e2ef3 100644 --- a/source/net/sourceforge/filebot/ui/FileBotList.java +++ b/source/net/sourceforge/filebot/ui/FileBotList.java @@ -18,8 +18,8 @@ import javax.swing.border.TitledBorder; import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler; import net.sourceforge.filebot.ui.transfer.TextFileExportHandler; import net.sourceforge.filebot.ui.transfer.TransferablePolicy; -import net.sourceforge.tuned.ui.DefaultFancyListCellRenderer; -import net.sourceforge.tuned.ui.TunedUtilities; +import net.sourceforge.filebot.util.ui.DefaultFancyListCellRenderer; +import net.sourceforge.filebot.util.ui.TunedUtilities; import ca.odell.glazedlists.BasicEventList; import ca.odell.glazedlists.EventList; import ca.odell.glazedlists.swing.EventListModel; diff --git a/source/net/sourceforge/filebot/ui/FileBotTabComponent.java b/source/net/sourceforge/filebot/ui/FileBotTabComponent.java index c3c5b122..e6cd9a40 100644 --- a/source/net/sourceforge/filebot/ui/FileBotTabComponent.java +++ b/source/net/sourceforge/filebot/ui/FileBotTabComponent.java @@ -13,8 +13,8 @@ import javax.swing.SwingConstants; import net.miginfocom.swing.MigLayout; import net.sourceforge.filebot.ResourceManager; -import net.sourceforge.tuned.ui.ProgressIndicator; -import net.sourceforge.tuned.ui.TunedUtilities; +import net.sourceforge.filebot.util.ui.ProgressIndicator; +import net.sourceforge.filebot.util.ui.TunedUtilities; public class FileBotTabComponent extends JComponent { diff --git a/source/net/sourceforge/filebot/ui/HeaderPanel.java b/source/net/sourceforge/filebot/ui/HeaderPanel.java index 3b2b1392..c863ada5 100644 --- a/source/net/sourceforge/filebot/ui/HeaderPanel.java +++ b/source/net/sourceforge/filebot/ui/HeaderPanel.java @@ -16,9 +16,9 @@ import javax.swing.SwingConstants; import javax.swing.border.EmptyBorder; import net.sourceforge.filebot.ResourceManager; -import net.sourceforge.tuned.ui.GradientStyle; -import net.sourceforge.tuned.ui.notification.SeparatorBorder; -import net.sourceforge.tuned.ui.notification.SeparatorBorder.Position; +import net.sourceforge.filebot.util.ui.GradientStyle; +import net.sourceforge.filebot.util.ui.notification.SeparatorBorder; +import net.sourceforge.filebot.util.ui.notification.SeparatorBorder.Position; class HeaderPanel extends JComponent { diff --git a/source/net/sourceforge/filebot/ui/HistoryPanel.java b/source/net/sourceforge/filebot/ui/HistoryPanel.java index 6d938348..7cf486eb 100644 --- a/source/net/sourceforge/filebot/ui/HistoryPanel.java +++ b/source/net/sourceforge/filebot/ui/HistoryPanel.java @@ -15,7 +15,7 @@ import javax.swing.JPanel; import javax.swing.SwingConstants; import net.miginfocom.swing.MigLayout; -import net.sourceforge.tuned.ui.LinkButton; +import net.sourceforge.filebot.util.ui.LinkButton; public class HistoryPanel extends JPanel { diff --git a/source/net/sourceforge/filebot/ui/LanguageComboBoxCellRenderer.java b/source/net/sourceforge/filebot/ui/LanguageComboBoxCellRenderer.java index f790ac78..ef8d99c6 100644 --- a/source/net/sourceforge/filebot/ui/LanguageComboBoxCellRenderer.java +++ b/source/net/sourceforge/filebot/ui/LanguageComboBoxCellRenderer.java @@ -12,7 +12,7 @@ import javax.swing.border.EmptyBorder; import net.sourceforge.filebot.Language; import net.sourceforge.filebot.ResourceManager; -import net.sourceforge.tuned.ui.DashedSeparator; +import net.sourceforge.filebot.util.ui.DashedSeparator; public class LanguageComboBoxCellRenderer implements ListCellRenderer { diff --git a/source/net/sourceforge/filebot/ui/MainFrame.java b/source/net/sourceforge/filebot/ui/MainFrame.java index 9e237eeb..f6e185e9 100644 --- a/source/net/sourceforge/filebot/ui/MainFrame.java +++ b/source/net/sourceforge/filebot/ui/MainFrame.java @@ -51,10 +51,10 @@ import net.sourceforge.filebot.ui.list.ListPanelBuilder; import net.sourceforge.filebot.ui.rename.RenamePanelBuilder; import net.sourceforge.filebot.ui.sfv.SfvPanelBuilder; import net.sourceforge.filebot.ui.subtitle.SubtitlePanelBuilder; -import net.sourceforge.tuned.PreferencesMap.PreferencesEntry; -import net.sourceforge.tuned.ui.DefaultFancyListCellRenderer; -import net.sourceforge.tuned.ui.ShadowBorder; -import net.sourceforge.tuned.ui.TunedUtilities; +import net.sourceforge.filebot.util.PreferencesMap.PreferencesEntry; +import net.sourceforge.filebot.util.ui.DefaultFancyListCellRenderer; +import net.sourceforge.filebot.util.ui.ShadowBorder; +import net.sourceforge.filebot.util.ui.TunedUtilities; public class MainFrame extends JFrame { diff --git a/source/net/sourceforge/filebot/ui/NotificationLogging.java b/source/net/sourceforge/filebot/ui/NotificationLogging.java index 76bd4dee..e2db10bc 100644 --- a/source/net/sourceforge/filebot/ui/NotificationLogging.java +++ b/source/net/sourceforge/filebot/ui/NotificationLogging.java @@ -3,7 +3,7 @@ package net.sourceforge.filebot.ui; import static net.sourceforge.filebot.Settings.*; -import static net.sourceforge.tuned.ui.notification.Direction.*; +import static net.sourceforge.filebot.util.ui.notification.Direction.*; import java.awt.GraphicsEnvironment; import java.util.logging.ConsoleHandler; @@ -16,10 +16,10 @@ import javax.swing.Icon; import javax.swing.SwingUtilities; import net.sourceforge.filebot.ResourceManager; -import net.sourceforge.tuned.ExceptionUtilities; -import net.sourceforge.tuned.ui.notification.MessageNotification; -import net.sourceforge.tuned.ui.notification.NotificationManager; -import net.sourceforge.tuned.ui.notification.QueueNotificationLayout; +import net.sourceforge.filebot.util.ExceptionUtilities; +import net.sourceforge.filebot.util.ui.notification.MessageNotification; +import net.sourceforge.filebot.util.ui.notification.NotificationManager; +import net.sourceforge.filebot.util.ui.notification.QueueNotificationLayout; public class NotificationLogging extends Handler { diff --git a/source/net/sourceforge/filebot/ui/SelectButtonTextField.java b/source/net/sourceforge/filebot/ui/SelectButtonTextField.java index a1ea8829..7911de6b 100644 --- a/source/net/sourceforge/filebot/ui/SelectButtonTextField.java +++ b/source/net/sourceforge/filebot/ui/SelectButtonTextField.java @@ -29,8 +29,8 @@ import javax.swing.text.JTextComponent; import net.miginfocom.swing.MigLayout; import net.sourceforge.filebot.ResourceManager; -import net.sourceforge.tuned.ui.SelectButton; -import net.sourceforge.tuned.ui.TunedUtilities; +import net.sourceforge.filebot.util.ui.SelectButton; +import net.sourceforge.filebot.util.ui.TunedUtilities; public class SelectButtonTextField extends JComponent { diff --git a/source/net/sourceforge/filebot/ui/SelectDialog.java b/source/net/sourceforge/filebot/ui/SelectDialog.java index 30499624..53dbf1af 100644 --- a/source/net/sourceforge/filebot/ui/SelectDialog.java +++ b/source/net/sourceforge/filebot/ui/SelectDialog.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.ui; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Component; import java.awt.Dimension; @@ -26,8 +26,8 @@ import javax.swing.SwingUtilities; import net.miginfocom.swing.MigLayout; import net.sourceforge.filebot.ResourceManager; -import net.sourceforge.tuned.ui.DefaultFancyListCellRenderer; -import net.sourceforge.tuned.ui.TunedUtilities; +import net.sourceforge.filebot.util.ui.DefaultFancyListCellRenderer; +import net.sourceforge.filebot.util.ui.TunedUtilities; public class SelectDialog extends JDialog { diff --git a/source/net/sourceforge/filebot/ui/SinglePanelFrame.java b/source/net/sourceforge/filebot/ui/SinglePanelFrame.java index 74d31b05..9cbbb7d0 100644 --- a/source/net/sourceforge/filebot/ui/SinglePanelFrame.java +++ b/source/net/sourceforge/filebot/ui/SinglePanelFrame.java @@ -14,7 +14,7 @@ import net.miginfocom.swing.MigLayout; import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.ui.transfer.TransferablePolicy; import net.sourceforge.filebot.ui.transfer.TransferablePolicy.TransferAction; -import net.sourceforge.tuned.ExceptionUtilities; +import net.sourceforge.filebot.util.ExceptionUtilities; public class SinglePanelFrame extends JFrame { diff --git a/source/net/sourceforge/filebot/ui/analyze/AttributeTool.java b/source/net/sourceforge/filebot/ui/analyze/AttributeTool.java index 9804e4f0..98f29b06 100644 --- a/source/net/sourceforge/filebot/ui/analyze/AttributeTool.java +++ b/source/net/sourceforge/filebot/ui/analyze/AttributeTool.java @@ -22,7 +22,7 @@ import net.sourceforge.filebot.ui.analyze.FileTree.FolderNode; import net.sourceforge.filebot.web.Episode; import net.sourceforge.filebot.web.Movie; import net.sourceforge.filebot.web.SearchResult; -import net.sourceforge.tuned.ui.LoadingOverlayPane; +import net.sourceforge.filebot.util.ui.LoadingOverlayPane; class AttributeTool extends Tool { diff --git a/source/net/sourceforge/filebot/ui/analyze/ExtractTool.java b/source/net/sourceforge/filebot/ui/analyze/ExtractTool.java index 8f1b77cc..763745ea 100644 --- a/source/net/sourceforge/filebot/ui/analyze/ExtractTool.java +++ b/source/net/sourceforge/filebot/ui/analyze/ExtractTool.java @@ -1,9 +1,9 @@ package net.sourceforge.filebot.ui.analyze; import static net.sourceforge.filebot.ui.NotificationLogging.*; -import static net.sourceforge.tuned.ExceptionUtilities.*; -import static net.sourceforge.tuned.FileUtilities.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.ExceptionUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Color; import java.awt.Window; @@ -37,13 +37,13 @@ import net.sourceforge.filebot.archive.Archive; import net.sourceforge.filebot.archive.FileMapper; import net.sourceforge.filebot.ui.analyze.FileTree.FolderNode; import net.sourceforge.filebot.vfs.FileInfo; -import net.sourceforge.tuned.FileUtilities; -import net.sourceforge.tuned.ui.GradientStyle; -import net.sourceforge.tuned.ui.LoadingOverlayPane; -import net.sourceforge.tuned.ui.ProgressDialog; -import net.sourceforge.tuned.ui.ProgressDialog.Cancellable; -import net.sourceforge.tuned.ui.SwingWorkerPropertyChangeAdapter; -import net.sourceforge.tuned.ui.notification.SeparatorBorder; +import net.sourceforge.filebot.util.FileUtilities; +import net.sourceforge.filebot.util.ui.GradientStyle; +import net.sourceforge.filebot.util.ui.LoadingOverlayPane; +import net.sourceforge.filebot.util.ui.ProgressDialog; +import net.sourceforge.filebot.util.ui.ProgressDialog.Cancellable; +import net.sourceforge.filebot.util.ui.SwingWorkerPropertyChangeAdapter; +import net.sourceforge.filebot.util.ui.notification.SeparatorBorder; class ExtractTool extends Tool { diff --git a/source/net/sourceforge/filebot/ui/analyze/FileTree.java b/source/net/sourceforge/filebot/ui/analyze/FileTree.java index a4ba1c47..92db5254 100644 --- a/source/net/sourceforge/filebot/ui/analyze/FileTree.java +++ b/source/net/sourceforge/filebot/ui/analyze/FileTree.java @@ -32,9 +32,9 @@ import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import net.sourceforge.filebot.ResourceManager; -import net.sourceforge.tuned.ExceptionUtilities; -import net.sourceforge.tuned.FilterIterator; -import net.sourceforge.tuned.TreeIterator; +import net.sourceforge.filebot.util.ExceptionUtilities; +import net.sourceforge.filebot.util.FilterIterator; +import net.sourceforge.filebot.util.TreeIterator; public class FileTree extends JTree { diff --git a/source/net/sourceforge/filebot/ui/analyze/FileTreeCellRenderer.java b/source/net/sourceforge/filebot/ui/analyze/FileTreeCellRenderer.java index 0c82c13d..2cd34b22 100644 --- a/source/net/sourceforge/filebot/ui/analyze/FileTreeCellRenderer.java +++ b/source/net/sourceforge/filebot/ui/analyze/FileTreeCellRenderer.java @@ -8,8 +8,8 @@ import javax.swing.JTree; import javax.swing.tree.TreeNode; import net.sourceforge.filebot.ResourceManager; -import net.sourceforge.tuned.ui.FancyTreeCellRenderer; -import net.sourceforge.tuned.ui.GradientStyle; +import net.sourceforge.filebot.util.ui.FancyTreeCellRenderer; +import net.sourceforge.filebot.util.ui.GradientStyle; public class FileTreeCellRenderer extends FancyTreeCellRenderer { diff --git a/source/net/sourceforge/filebot/ui/analyze/FileTreePanel.java b/source/net/sourceforge/filebot/ui/analyze/FileTreePanel.java index 6e7ebc7e..aeace0e1 100644 --- a/source/net/sourceforge/filebot/ui/analyze/FileTreePanel.java +++ b/source/net/sourceforge/filebot/ui/analyze/FileTreePanel.java @@ -20,8 +20,8 @@ import net.miginfocom.swing.MigLayout; import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler; import net.sourceforge.filebot.ui.transfer.LoadAction; -import net.sourceforge.tuned.ui.LoadingOverlayPane; -import net.sourceforge.tuned.ui.TunedUtilities; +import net.sourceforge.filebot.util.ui.LoadingOverlayPane; +import net.sourceforge.filebot.util.ui.TunedUtilities; class FileTreePanel extends JComponent { diff --git a/source/net/sourceforge/filebot/ui/analyze/FileTreeTransferablePolicy.java b/source/net/sourceforge/filebot/ui/analyze/FileTreeTransferablePolicy.java index 4e5503f7..1aa1e926 100644 --- a/source/net/sourceforge/filebot/ui/analyze/FileTreeTransferablePolicy.java +++ b/source/net/sourceforge/filebot/ui/analyze/FileTreeTransferablePolicy.java @@ -12,9 +12,9 @@ import net.sourceforge.filebot.ui.analyze.FileTree.AbstractTreeNode; import net.sourceforge.filebot.ui.analyze.FileTree.FileNode; import net.sourceforge.filebot.ui.analyze.FileTree.FolderNode; import net.sourceforge.filebot.ui.transfer.BackgroundFileTransferablePolicy; -import net.sourceforge.tuned.ExceptionUtilities; -import net.sourceforge.tuned.FastFile; -import net.sourceforge.tuned.FileUtilities; +import net.sourceforge.filebot.util.ExceptionUtilities; +import net.sourceforge.filebot.util.FastFile; +import net.sourceforge.filebot.util.FileUtilities; class FileTreeTransferablePolicy extends BackgroundFileTransferablePolicy { diff --git a/source/net/sourceforge/filebot/ui/analyze/SplitTool.java b/source/net/sourceforge/filebot/ui/analyze/SplitTool.java index 50413017..196efe0d 100644 --- a/source/net/sourceforge/filebot/ui/analyze/SplitTool.java +++ b/source/net/sourceforge/filebot/ui/analyze/SplitTool.java @@ -22,10 +22,10 @@ import javax.swing.tree.TreeModel; import net.miginfocom.swing.MigLayout; import net.sourceforge.filebot.ui.analyze.FileTree.FolderNode; import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler; -import net.sourceforge.tuned.FileUtilities; -import net.sourceforge.tuned.ui.GradientStyle; -import net.sourceforge.tuned.ui.LoadingOverlayPane; -import net.sourceforge.tuned.ui.notification.SeparatorBorder; +import net.sourceforge.filebot.util.FileUtilities; +import net.sourceforge.filebot.util.ui.GradientStyle; +import net.sourceforge.filebot.util.ui.LoadingOverlayPane; +import net.sourceforge.filebot.util.ui.notification.SeparatorBorder; class SplitTool extends Tool implements ChangeListener { diff --git a/source/net/sourceforge/filebot/ui/analyze/Tool.java b/source/net/sourceforge/filebot/ui/analyze/Tool.java index 6da0e7fc..39bed7ae 100644 --- a/source/net/sourceforge/filebot/ui/analyze/Tool.java +++ b/source/net/sourceforge/filebot/ui/analyze/Tool.java @@ -13,9 +13,9 @@ import javax.swing.SwingWorker; import net.sourceforge.filebot.ui.analyze.FileTree.FileNode; import net.sourceforge.filebot.ui.analyze.FileTree.FolderNode; -import net.sourceforge.tuned.ExceptionUtilities; -import net.sourceforge.tuned.FileUtilities; -import net.sourceforge.tuned.ui.LoadingOverlayPane; +import net.sourceforge.filebot.util.ExceptionUtilities; +import net.sourceforge.filebot.util.FileUtilities; +import net.sourceforge.filebot.util.ui.LoadingOverlayPane; abstract class Tool extends JComponent { diff --git a/source/net/sourceforge/filebot/ui/analyze/TypeTool.java b/source/net/sourceforge/filebot/ui/analyze/TypeTool.java index 16e5f171..e47dc042 100644 --- a/source/net/sourceforge/filebot/ui/analyze/TypeTool.java +++ b/source/net/sourceforge/filebot/ui/analyze/TypeTool.java @@ -19,8 +19,8 @@ import javax.swing.tree.TreeModel; import net.miginfocom.swing.MigLayout; import net.sourceforge.filebot.ui.analyze.FileTree.FolderNode; import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler; -import net.sourceforge.tuned.FileUtilities; -import net.sourceforge.tuned.ui.LoadingOverlayPane; +import net.sourceforge.filebot.util.FileUtilities; +import net.sourceforge.filebot.util.ui.LoadingOverlayPane; class TypeTool extends Tool { diff --git a/source/net/sourceforge/filebot/ui/episodelist/EpisodeListPanel.java b/source/net/sourceforge/filebot/ui/episodelist/EpisodeListPanel.java index 5b4e1935..8f5df5fd 100644 --- a/source/net/sourceforge/filebot/ui/episodelist/EpisodeListPanel.java +++ b/source/net/sourceforge/filebot/ui/episodelist/EpisodeListPanel.java @@ -47,11 +47,11 @@ import net.sourceforge.filebot.web.EpisodeListProvider; import net.sourceforge.filebot.web.SearchResult; import net.sourceforge.filebot.web.SeasonOutOfBoundsException; import net.sourceforge.filebot.web.SortOrder; -import net.sourceforge.tuned.StringUtilities; -import net.sourceforge.tuned.ui.LabelProvider; -import net.sourceforge.tuned.ui.SelectButton; -import net.sourceforge.tuned.ui.SimpleLabelProvider; -import net.sourceforge.tuned.ui.TunedUtilities; +import net.sourceforge.filebot.util.StringUtilities; +import net.sourceforge.filebot.util.ui.LabelProvider; +import net.sourceforge.filebot.util.ui.SelectButton; +import net.sourceforge.filebot.util.ui.SimpleLabelProvider; +import net.sourceforge.filebot.util.ui.TunedUtilities; public class EpisodeListPanel extends AbstractSearchPanel { diff --git a/source/net/sourceforge/filebot/ui/list/FileListTransferablePolicy.java b/source/net/sourceforge/filebot/ui/list/FileListTransferablePolicy.java index acfbcec1..28d42b56 100644 --- a/source/net/sourceforge/filebot/ui/list/FileListTransferablePolicy.java +++ b/source/net/sourceforge/filebot/ui/list/FileListTransferablePolicy.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.ui.list; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; import java.io.IOException; @@ -13,7 +13,7 @@ import net.sourceforge.filebot.MediaTypes; import net.sourceforge.filebot.torrent.Torrent; import net.sourceforge.filebot.ui.FileBotList; import net.sourceforge.filebot.ui.transfer.FileTransferablePolicy; -import net.sourceforge.tuned.FileUtilities; +import net.sourceforge.filebot.util.FileUtilities; class FileListTransferablePolicy extends FileTransferablePolicy { diff --git a/source/net/sourceforge/filebot/ui/list/ListPanel.java b/source/net/sourceforge/filebot/ui/list/ListPanel.java index 7993c33f..81588327 100644 --- a/source/net/sourceforge/filebot/ui/list/ListPanel.java +++ b/source/net/sourceforge/filebot/ui/list/ListPanel.java @@ -37,8 +37,8 @@ import net.sourceforge.filebot.ui.FileBotList; import net.sourceforge.filebot.ui.FileBotListExportHandler; import net.sourceforge.filebot.ui.transfer.LoadAction; import net.sourceforge.filebot.ui.transfer.SaveAction; -import net.sourceforge.tuned.ExceptionUtilities; -import net.sourceforge.tuned.ui.TunedUtilities; +import net.sourceforge.filebot.util.ExceptionUtilities; +import net.sourceforge.filebot.util.ui.TunedUtilities; public class ListPanel extends JComponent { diff --git a/source/net/sourceforge/filebot/ui/rename/AudioFingerprintMatcher.java b/source/net/sourceforge/filebot/ui/rename/AudioFingerprintMatcher.java index 05c0abb1..a92f38b2 100644 --- a/source/net/sourceforge/filebot/ui/rename/AudioFingerprintMatcher.java +++ b/source/net/sourceforge/filebot/ui/rename/AudioFingerprintMatcher.java @@ -1,7 +1,7 @@ package net.sourceforge.filebot.ui.rename; import static net.sourceforge.filebot.MediaTypes.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.awt.Component; import java.io.File; diff --git a/source/net/sourceforge/filebot/ui/rename/BindingDialog.java b/source/net/sourceforge/filebot/ui/rename/BindingDialog.java index 115d3e8f..3ea1ce17 100644 --- a/source/net/sourceforge/filebot/ui/rename/BindingDialog.java +++ b/source/net/sourceforge/filebot/ui/rename/BindingDialog.java @@ -3,7 +3,7 @@ package net.sourceforge.filebot.ui.rename; import static net.sourceforge.filebot.MediaTypes.*; import static net.sourceforge.filebot.Settings.*; import static net.sourceforge.filebot.ui.NotificationLogging.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Color; import java.awt.Component; @@ -61,8 +61,8 @@ import net.sourceforge.filebot.media.MetaAttributes; import net.sourceforge.filebot.mediainfo.MediaInfo; import net.sourceforge.filebot.mediainfo.MediaInfo.StreamKind; import net.sourceforge.filebot.mediainfo.MediaInfoException; -import net.sourceforge.tuned.DefaultThreadFactory; -import net.sourceforge.tuned.ui.LazyDocumentListener; +import net.sourceforge.filebot.util.DefaultThreadFactory; +import net.sourceforge.filebot.util.ui.LazyDocumentListener; class BindingDialog extends JDialog { diff --git a/source/net/sourceforge/filebot/ui/rename/CharacterHighlightPainter.java b/source/net/sourceforge/filebot/ui/rename/CharacterHighlightPainter.java index cf0c60b8..47c6d296 100644 --- a/source/net/sourceforge/filebot/ui/rename/CharacterHighlightPainter.java +++ b/source/net/sourceforge/filebot/ui/rename/CharacterHighlightPainter.java @@ -17,7 +17,7 @@ import javax.swing.text.BadLocationException; import javax.swing.text.Highlighter; import javax.swing.text.JTextComponent; -import net.sourceforge.tuned.ui.GradientStyle; +import net.sourceforge.filebot.util.ui.GradientStyle; class CharacterHighlightPainter implements Highlighter.HighlightPainter { diff --git a/source/net/sourceforge/filebot/ui/rename/EpisodeListMatcher.java b/source/net/sourceforge/filebot/ui/rename/EpisodeListMatcher.java index 22c3d681..b7e1475a 100644 --- a/source/net/sourceforge/filebot/ui/rename/EpisodeListMatcher.java +++ b/source/net/sourceforge/filebot/ui/rename/EpisodeListMatcher.java @@ -4,9 +4,9 @@ import static java.util.Collections.*; import static net.sourceforge.filebot.MediaTypes.*; import static net.sourceforge.filebot.Settings.*; import static net.sourceforge.filebot.media.MediaDetection.*; -import static net.sourceforge.tuned.FileUtilities.*; -import static net.sourceforge.tuned.StringUtilities.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; +import static net.sourceforge.filebot.util.StringUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Component; import java.awt.Dimension; diff --git a/source/net/sourceforge/filebot/ui/rename/FileNameFormatter.java b/source/net/sourceforge/filebot/ui/rename/FileNameFormatter.java index 0b541774..cb477bf7 100644 --- a/source/net/sourceforge/filebot/ui/rename/FileNameFormatter.java +++ b/source/net/sourceforge/filebot/ui/rename/FileNameFormatter.java @@ -7,7 +7,7 @@ import java.util.Map; import net.sourceforge.filebot.similarity.Match; import net.sourceforge.filebot.vfs.FileInfo; -import net.sourceforge.tuned.FileUtilities; +import net.sourceforge.filebot.util.FileUtilities; class FileNameFormatter implements MatchFormatter { diff --git a/source/net/sourceforge/filebot/ui/rename/FilesListTransferablePolicy.java b/source/net/sourceforge/filebot/ui/rename/FilesListTransferablePolicy.java index a4a2c721..c75cbecd 100644 --- a/source/net/sourceforge/filebot/ui/rename/FilesListTransferablePolicy.java +++ b/source/net/sourceforge/filebot/ui/rename/FilesListTransferablePolicy.java @@ -3,7 +3,7 @@ package net.sourceforge.filebot.ui.rename; import static java.util.Arrays.*; import static net.sourceforge.filebot.MediaTypes.*; import static net.sourceforge.filebot.ui.transfer.FileTransferable.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.awt.datatransfer.Transferable; import java.io.File; @@ -17,7 +17,7 @@ import java.util.logging.Logger; import net.sourceforge.filebot.media.MediaDetection; import net.sourceforge.filebot.ui.transfer.FileTransferablePolicy; -import net.sourceforge.tuned.FastFile; +import net.sourceforge.filebot.util.FastFile; class FilesListTransferablePolicy extends FileTransferablePolicy { diff --git a/source/net/sourceforge/filebot/ui/rename/FormatDialog.java b/source/net/sourceforge/filebot/ui/rename/FormatDialog.java index 293beb9b..0cd2e48e 100644 --- a/source/net/sourceforge/filebot/ui/rename/FormatDialog.java +++ b/source/net/sourceforge/filebot/ui/rename/FormatDialog.java @@ -3,8 +3,8 @@ package net.sourceforge.filebot.ui.rename; import static java.awt.Font.*; import static javax.swing.BorderFactory.*; import static net.sourceforge.filebot.ui.NotificationLogging.*; -import static net.sourceforge.tuned.ExceptionUtilities.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.ExceptionUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Color; import java.awt.Component; @@ -67,17 +67,17 @@ import net.sourceforge.filebot.format.MediaBindingBean; import net.sourceforge.filebot.web.AudioTrackFormat; import net.sourceforge.filebot.web.EpisodeFormat; import net.sourceforge.filebot.web.MovieFormat; -import net.sourceforge.tuned.DefaultThreadFactory; -import net.sourceforge.tuned.ExceptionUtilities; -import net.sourceforge.tuned.PreferencesList; -import net.sourceforge.tuned.PreferencesMap.PreferencesEntry; -import net.sourceforge.tuned.ui.GradientStyle; -import net.sourceforge.tuned.ui.LazyDocumentListener; -import net.sourceforge.tuned.ui.LinkButton; -import net.sourceforge.tuned.ui.ProgressIndicator; -import net.sourceforge.tuned.ui.TunedUtilities; -import net.sourceforge.tuned.ui.notification.SeparatorBorder; -import net.sourceforge.tuned.ui.notification.SeparatorBorder.Position; +import net.sourceforge.filebot.util.DefaultThreadFactory; +import net.sourceforge.filebot.util.ExceptionUtilities; +import net.sourceforge.filebot.util.PreferencesList; +import net.sourceforge.filebot.util.PreferencesMap.PreferencesEntry; +import net.sourceforge.filebot.util.ui.GradientStyle; +import net.sourceforge.filebot.util.ui.LazyDocumentListener; +import net.sourceforge.filebot.util.ui.LinkButton; +import net.sourceforge.filebot.util.ui.ProgressIndicator; +import net.sourceforge.filebot.util.ui.TunedUtilities; +import net.sourceforge.filebot.util.ui.notification.SeparatorBorder; +import net.sourceforge.filebot.util.ui.notification.SeparatorBorder.Position; import org.fife.ui.rsyntaxtextarea.RSyntaxDocument; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; diff --git a/source/net/sourceforge/filebot/ui/rename/HighlightListCellRenderer.java b/source/net/sourceforge/filebot/ui/rename/HighlightListCellRenderer.java index 6e325fcc..8d508c86 100644 --- a/source/net/sourceforge/filebot/ui/rename/HighlightListCellRenderer.java +++ b/source/net/sourceforge/filebot/ui/rename/HighlightListCellRenderer.java @@ -19,8 +19,8 @@ import javax.swing.text.BadLocationException; import javax.swing.text.Highlighter; import javax.swing.text.JTextComponent; -import net.sourceforge.tuned.ui.AbstractFancyListCellRenderer; -import net.sourceforge.tuned.ui.TunedUtilities; +import net.sourceforge.filebot.util.ui.AbstractFancyListCellRenderer; +import net.sourceforge.filebot.util.ui.TunedUtilities; class HighlightListCellRenderer extends AbstractFancyListCellRenderer { diff --git a/source/net/sourceforge/filebot/ui/rename/HistoryDialog.java b/source/net/sourceforge/filebot/ui/rename/HistoryDialog.java index 0ab8d3ef..aeea8b1f 100644 --- a/source/net/sourceforge/filebot/ui/rename/HistoryDialog.java +++ b/source/net/sourceforge/filebot/ui/rename/HistoryDialog.java @@ -4,7 +4,7 @@ import static java.awt.Font.*; import static java.util.Collections.*; import static java.util.regex.Pattern.*; import static javax.swing.JOptionPane.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.awt.Color; import java.awt.Component; @@ -73,12 +73,12 @@ import net.sourceforge.filebot.ui.transfer.FileTransferablePolicy; import net.sourceforge.filebot.ui.transfer.LoadAction; import net.sourceforge.filebot.ui.transfer.SaveAction; import net.sourceforge.filebot.ui.transfer.TransferablePolicy.TransferAction; -import net.sourceforge.tuned.FileUtilities; -import net.sourceforge.tuned.FileUtilities.ExtensionFileFilter; -import net.sourceforge.tuned.ui.GradientStyle; -import net.sourceforge.tuned.ui.LazyDocumentListener; -import net.sourceforge.tuned.ui.notification.SeparatorBorder; -import net.sourceforge.tuned.ui.notification.SeparatorBorder.Position; +import net.sourceforge.filebot.util.FileUtilities; +import net.sourceforge.filebot.util.FileUtilities.ExtensionFileFilter; +import net.sourceforge.filebot.util.ui.GradientStyle; +import net.sourceforge.filebot.util.ui.LazyDocumentListener; +import net.sourceforge.filebot.util.ui.notification.SeparatorBorder; +import net.sourceforge.filebot.util.ui.notification.SeparatorBorder.Position; class HistoryDialog extends JDialog { diff --git a/source/net/sourceforge/filebot/ui/rename/MatchAction.java b/source/net/sourceforge/filebot/ui/rename/MatchAction.java index 3175b4a9..3084a427 100644 --- a/source/net/sourceforge/filebot/ui/rename/MatchAction.java +++ b/source/net/sourceforge/filebot/ui/rename/MatchAction.java @@ -1,6 +1,6 @@ package net.sourceforge.filebot.ui.rename; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Cursor; import java.awt.Window; @@ -22,9 +22,9 @@ import net.sourceforge.filebot.similarity.EpisodeMetrics; import net.sourceforge.filebot.similarity.Match; import net.sourceforge.filebot.similarity.Matcher; import net.sourceforge.filebot.similarity.SimilarityMetric; -import net.sourceforge.tuned.ui.ProgressDialog; -import net.sourceforge.tuned.ui.ProgressDialog.Cancellable; -import net.sourceforge.tuned.ui.SwingWorkerPropertyChangeAdapter; +import net.sourceforge.filebot.util.ui.ProgressDialog; +import net.sourceforge.filebot.util.ui.ProgressDialog.Cancellable; +import net.sourceforge.filebot.util.ui.SwingWorkerPropertyChangeAdapter; class MatchAction extends AbstractAction { diff --git a/source/net/sourceforge/filebot/ui/rename/MovieFormatter.java b/source/net/sourceforge/filebot/ui/rename/MovieFormatter.java index 3e35b1f8..ecfe2893 100644 --- a/source/net/sourceforge/filebot/ui/rename/MovieFormatter.java +++ b/source/net/sourceforge/filebot/ui/rename/MovieFormatter.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.ui.rename; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.util.Formatter; import java.util.Map; diff --git a/source/net/sourceforge/filebot/ui/rename/MovieHashMatcher.java b/source/net/sourceforge/filebot/ui/rename/MovieHashMatcher.java index 7885d01c..913ac712 100644 --- a/source/net/sourceforge/filebot/ui/rename/MovieHashMatcher.java +++ b/source/net/sourceforge/filebot/ui/rename/MovieHashMatcher.java @@ -7,8 +7,8 @@ import static net.sourceforge.filebot.Settings.*; import static net.sourceforge.filebot.media.MediaDetection.*; import static net.sourceforge.filebot.similarity.CommonSequenceMatcher.*; import static net.sourceforge.filebot.similarity.Normalization.*; -import static net.sourceforge.tuned.FileUtilities.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Component; import java.awt.Dimension; @@ -54,7 +54,7 @@ import net.sourceforge.filebot.web.Movie; import net.sourceforge.filebot.web.MovieIdentificationService; import net.sourceforge.filebot.web.MoviePart; import net.sourceforge.filebot.web.SortOrder; -import net.sourceforge.tuned.FileUtilities.ParentFilter; +import net.sourceforge.filebot.util.FileUtilities.ParentFilter; class MovieHashMatcher implements AutoCompleteMatcher { diff --git a/source/net/sourceforge/filebot/ui/rename/NamesListTransferablePolicy.java b/source/net/sourceforge/filebot/ui/rename/NamesListTransferablePolicy.java index 8937c098..7a9f865b 100644 --- a/source/net/sourceforge/filebot/ui/rename/NamesListTransferablePolicy.java +++ b/source/net/sourceforge/filebot/ui/rename/NamesListTransferablePolicy.java @@ -3,7 +3,7 @@ package net.sourceforge.filebot.ui.rename; import static java.awt.datatransfer.DataFlavor.*; import static net.sourceforge.filebot.hash.VerificationUtilities.*; import static net.sourceforge.filebot.ui.transfer.FileTransferable.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; @@ -22,7 +22,7 @@ import net.sourceforge.filebot.ui.transfer.ArrayTransferable; import net.sourceforge.filebot.ui.transfer.FileTransferablePolicy; import net.sourceforge.filebot.vfs.SimpleFileInfo; import net.sourceforge.filebot.web.Episode; -import net.sourceforge.tuned.FastFile; +import net.sourceforge.filebot.util.FastFile; class NamesListTransferablePolicy extends FileTransferablePolicy { diff --git a/source/net/sourceforge/filebot/ui/rename/RenameAction.java b/source/net/sourceforge/filebot/ui/rename/RenameAction.java index d71c8ae3..9c538dc8 100644 --- a/source/net/sourceforge/filebot/ui/rename/RenameAction.java +++ b/source/net/sourceforge/filebot/ui/rename/RenameAction.java @@ -4,9 +4,9 @@ import static java.util.Collections.*; import static javax.swing.JOptionPane.*; import static net.sourceforge.filebot.Settings.*; import static net.sourceforge.filebot.ui.NotificationLogging.*; -import static net.sourceforge.tuned.ExceptionUtilities.*; -import static net.sourceforge.tuned.FileUtilities.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.ExceptionUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Cursor; import java.awt.Dimension; @@ -46,9 +46,9 @@ import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.StandardRenameAction; import net.sourceforge.filebot.media.MediaDetection; import net.sourceforge.filebot.similarity.Match; -import net.sourceforge.tuned.ui.ProgressDialog; -import net.sourceforge.tuned.ui.ProgressDialog.Cancellable; -import net.sourceforge.tuned.ui.SwingWorkerPropertyChangeAdapter; +import net.sourceforge.filebot.util.ui.ProgressDialog; +import net.sourceforge.filebot.util.ui.ProgressDialog.Cancellable; +import net.sourceforge.filebot.util.ui.SwingWorkerPropertyChangeAdapter; class RenameAction extends AbstractAction { diff --git a/source/net/sourceforge/filebot/ui/rename/RenameListCellRenderer.java b/source/net/sourceforge/filebot/ui/rename/RenameListCellRenderer.java index 524fb2ac..b23ad99c 100644 --- a/source/net/sourceforge/filebot/ui/rename/RenameListCellRenderer.java +++ b/source/net/sourceforge/filebot/ui/rename/RenameListCellRenderer.java @@ -1,8 +1,8 @@ package net.sourceforge.filebot.ui.rename; import static net.sourceforge.filebot.similarity.EpisodeMetrics.*; -import static net.sourceforge.tuned.FileUtilities.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.AlphaComposite; import java.awt.Color; @@ -28,9 +28,9 @@ import net.sourceforge.filebot.similarity.MetricMin; import net.sourceforge.filebot.similarity.SimilarityMetric; import net.sourceforge.filebot.ui.rename.RenameModel.FormattedFuture; import net.sourceforge.filebot.web.Episode; -import net.sourceforge.tuned.FileUtilities; -import net.sourceforge.tuned.ui.DefaultFancyListCellRenderer; -import net.sourceforge.tuned.ui.GradientStyle; +import net.sourceforge.filebot.util.FileUtilities; +import net.sourceforge.filebot.util.ui.DefaultFancyListCellRenderer; +import net.sourceforge.filebot.util.ui.GradientStyle; class RenameListCellRenderer extends DefaultFancyListCellRenderer { diff --git a/source/net/sourceforge/filebot/ui/rename/RenameModel.java b/source/net/sourceforge/filebot/ui/rename/RenameModel.java index 2110a231..8c37ba28 100644 --- a/source/net/sourceforge/filebot/ui/rename/RenameModel.java +++ b/source/net/sourceforge/filebot/ui/rename/RenameModel.java @@ -1,6 +1,6 @@ package net.sourceforge.filebot.ui.rename; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -23,8 +23,8 @@ import javax.swing.SwingWorker; import javax.swing.SwingWorker.StateValue; import net.sourceforge.filebot.similarity.Match; -import net.sourceforge.tuned.FileUtilities; -import net.sourceforge.tuned.ui.TunedUtilities; +import net.sourceforge.filebot.util.FileUtilities; +import net.sourceforge.filebot.util.ui.TunedUtilities; import ca.odell.glazedlists.EventList; import ca.odell.glazedlists.TransformedList; import ca.odell.glazedlists.event.ListEvent; diff --git a/source/net/sourceforge/filebot/ui/rename/RenamePanel.java b/source/net/sourceforge/filebot/ui/rename/RenamePanel.java index cf32a64b..00ce7e10 100644 --- a/source/net/sourceforge/filebot/ui/rename/RenamePanel.java +++ b/source/net/sourceforge/filebot/ui/rename/RenamePanel.java @@ -5,9 +5,9 @@ import static javax.swing.JOptionPane.*; import static javax.swing.KeyStroke.*; import static javax.swing.SwingUtilities.*; import static net.sourceforge.filebot.ui.NotificationLogging.*; -import static net.sourceforge.tuned.ExceptionUtilities.*; -import static net.sourceforge.tuned.ui.LoadingOverlayPane.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.ExceptionUtilities.*; +import static net.sourceforge.filebot.util.ui.LoadingOverlayPane.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Component; import java.awt.Cursor; @@ -68,9 +68,9 @@ import net.sourceforge.filebot.web.MovieFormat; import net.sourceforge.filebot.web.MovieIdentificationService; import net.sourceforge.filebot.web.MusicIdentificationService; import net.sourceforge.filebot.web.SortOrder; -import net.sourceforge.tuned.PreferencesMap.PreferencesEntry; -import net.sourceforge.tuned.ui.ActionPopup; -import net.sourceforge.tuned.ui.LoadingOverlayPane; +import net.sourceforge.filebot.util.PreferencesMap.PreferencesEntry; +import net.sourceforge.filebot.util.ui.ActionPopup; +import net.sourceforge.filebot.util.ui.LoadingOverlayPane; import ca.odell.glazedlists.EventList; import ca.odell.glazedlists.ListSelection; import ca.odell.glazedlists.swing.EventSelectionModel; diff --git a/source/net/sourceforge/filebot/ui/rename/ValidateDialog.java b/source/net/sourceforge/filebot/ui/rename/ValidateDialog.java index 10a81658..5b610e3e 100644 --- a/source/net/sourceforge/filebot/ui/rename/ValidateDialog.java +++ b/source/net/sourceforge/filebot/ui/rename/ValidateDialog.java @@ -4,8 +4,8 @@ package net.sourceforge.filebot.ui.rename; import static java.util.Collections.*; import static net.sourceforge.filebot.Settings.*; -import static net.sourceforge.tuned.FileUtilities.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Color; import java.awt.Component; diff --git a/source/net/sourceforge/filebot/ui/sfv/ChecksumCell.java b/source/net/sourceforge/filebot/ui/sfv/ChecksumCell.java index aa119be8..c2143f4d 100644 --- a/source/net/sourceforge/filebot/ui/sfv/ChecksumCell.java +++ b/source/net/sourceforge/filebot/ui/sfv/ChecksumCell.java @@ -13,7 +13,7 @@ import javax.swing.SwingWorker.StateValue; import javax.swing.event.SwingPropertyChangeSupport; import net.sourceforge.filebot.hash.HashType; -import net.sourceforge.tuned.ExceptionUtilities; +import net.sourceforge.filebot.util.ExceptionUtilities; class ChecksumCell { diff --git a/source/net/sourceforge/filebot/ui/sfv/ChecksumCellRenderer.java b/source/net/sourceforge/filebot/ui/sfv/ChecksumCellRenderer.java index e248d008..a0b7a304 100644 --- a/source/net/sourceforge/filebot/ui/sfv/ChecksumCellRenderer.java +++ b/source/net/sourceforge/filebot/ui/sfv/ChecksumCellRenderer.java @@ -3,7 +3,7 @@ package net.sourceforge.filebot.ui.sfv; import static java.awt.Font.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Color; import java.awt.Component; @@ -14,7 +14,7 @@ import javax.swing.SwingWorker; import javax.swing.SwingWorker.StateValue; import javax.swing.table.DefaultTableCellRenderer; -import net.sourceforge.tuned.ExceptionUtilities; +import net.sourceforge.filebot.util.ExceptionUtilities; public class ChecksumCellRenderer extends DefaultTableCellRenderer { diff --git a/source/net/sourceforge/filebot/ui/sfv/ChecksumComputationService.java b/source/net/sourceforge/filebot/ui/sfv/ChecksumComputationService.java index 433235aa..42bb4289 100644 --- a/source/net/sourceforge/filebot/ui/sfv/ChecksumComputationService.java +++ b/source/net/sourceforge/filebot/ui/sfv/ChecksumComputationService.java @@ -15,7 +15,7 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import net.sourceforge.tuned.DefaultThreadFactory; +import net.sourceforge.filebot.util.DefaultThreadFactory; class ChecksumComputationService { diff --git a/source/net/sourceforge/filebot/ui/sfv/ChecksumTable.java b/source/net/sourceforge/filebot/ui/sfv/ChecksumTable.java index d1f94feb..63b73a22 100644 --- a/source/net/sourceforge/filebot/ui/sfv/ChecksumTable.java +++ b/source/net/sourceforge/filebot/ui/sfv/ChecksumTable.java @@ -12,7 +12,7 @@ import javax.swing.ListSelectionModel; import javax.swing.table.JTableHeader; import javax.swing.table.TableColumn; -import net.sourceforge.tuned.ui.TunedUtilities.DragDropRowTableUI; +import net.sourceforge.filebot.util.ui.TunedUtilities.DragDropRowTableUI; class ChecksumTable extends JTable { diff --git a/source/net/sourceforge/filebot/ui/sfv/ChecksumTableExportHandler.java b/source/net/sourceforge/filebot/ui/sfv/ChecksumTableExportHandler.java index 01144143..b4f61f4c 100644 --- a/source/net/sourceforge/filebot/ui/sfv/ChecksumTableExportHandler.java +++ b/source/net/sourceforge/filebot/ui/sfv/ChecksumTableExportHandler.java @@ -9,7 +9,7 @@ import java.io.PrintWriter; import net.sourceforge.filebot.hash.HashType; import net.sourceforge.filebot.hash.VerificationFileWriter; import net.sourceforge.filebot.ui.transfer.TextFileExportHandler; -import net.sourceforge.tuned.FileUtilities; +import net.sourceforge.filebot.util.FileUtilities; class ChecksumTableExportHandler extends TextFileExportHandler { diff --git a/source/net/sourceforge/filebot/ui/sfv/ChecksumTableModel.java b/source/net/sourceforge/filebot/ui/sfv/ChecksumTableModel.java index 64d831ed..2ac3029a 100644 --- a/source/net/sourceforge/filebot/ui/sfv/ChecksumTableModel.java +++ b/source/net/sourceforge/filebot/ui/sfv/ChecksumTableModel.java @@ -19,8 +19,8 @@ import java.util.Set; import javax.swing.table.AbstractTableModel; import net.sourceforge.filebot.hash.HashType; -import net.sourceforge.tuned.FastFile; -import net.sourceforge.tuned.FileUtilities; +import net.sourceforge.filebot.util.FastFile; +import net.sourceforge.filebot.util.FileUtilities; class ChecksumTableModel extends AbstractTableModel { diff --git a/source/net/sourceforge/filebot/ui/sfv/ChecksumTableTransferablePolicy.java b/source/net/sourceforge/filebot/ui/sfv/ChecksumTableTransferablePolicy.java index a60cdac5..e4e92563 100644 --- a/source/net/sourceforge/filebot/ui/sfv/ChecksumTableTransferablePolicy.java +++ b/source/net/sourceforge/filebot/ui/sfv/ChecksumTableTransferablePolicy.java @@ -5,7 +5,7 @@ package net.sourceforge.filebot.ui.sfv; import static java.util.Collections.*; import static net.sourceforge.filebot.hash.VerificationUtilities.*; import static net.sourceforge.filebot.ui.NotificationLogging.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; import java.io.IOException; @@ -20,7 +20,7 @@ import net.sourceforge.filebot.MediaTypes; import net.sourceforge.filebot.hash.HashType; import net.sourceforge.filebot.hash.VerificationFileReader; import net.sourceforge.filebot.ui.transfer.BackgroundFileTransferablePolicy; -import net.sourceforge.tuned.ExceptionUtilities; +import net.sourceforge.filebot.util.ExceptionUtilities; class ChecksumTableTransferablePolicy extends BackgroundFileTransferablePolicy { diff --git a/source/net/sourceforge/filebot/ui/sfv/SfvPanel.java b/source/net/sourceforge/filebot/ui/sfv/SfvPanel.java index 473ec0ad..525284bc 100644 --- a/source/net/sourceforge/filebot/ui/sfv/SfvPanel.java +++ b/source/net/sourceforge/filebot/ui/sfv/SfvPanel.java @@ -36,8 +36,8 @@ import net.sourceforge.filebot.ui.SelectDialog; import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler; import net.sourceforge.filebot.ui.transfer.LoadAction; import net.sourceforge.filebot.ui.transfer.SaveAction; -import net.sourceforge.tuned.FileUtilities; -import net.sourceforge.tuned.ui.TunedUtilities; +import net.sourceforge.filebot.util.FileUtilities; +import net.sourceforge.filebot.util.ui.TunedUtilities; public class SfvPanel extends JComponent { diff --git a/source/net/sourceforge/filebot/ui/subtitle/SubtitleAutoMatchDialog.java b/source/net/sourceforge/filebot/ui/subtitle/SubtitleAutoMatchDialog.java index c1393a67..b90a88b3 100644 --- a/source/net/sourceforge/filebot/ui/subtitle/SubtitleAutoMatchDialog.java +++ b/source/net/sourceforge/filebot/ui/subtitle/SubtitleAutoMatchDialog.java @@ -3,8 +3,8 @@ package net.sourceforge.filebot.ui.subtitle; import static javax.swing.BorderFactory.*; import static javax.swing.JOptionPane.*; import static net.sourceforge.filebot.subtitle.SubtitleUtilities.*; -import static net.sourceforge.tuned.FileUtilities.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Color; import java.awt.Component; @@ -66,10 +66,10 @@ import net.sourceforge.filebot.vfs.MemoryFile; import net.sourceforge.filebot.web.SubtitleDescriptor; import net.sourceforge.filebot.web.SubtitleProvider; import net.sourceforge.filebot.web.VideoHashSubtitleService; -import net.sourceforge.tuned.ui.AbstractBean; -import net.sourceforge.tuned.ui.EmptySelectionModel; -import net.sourceforge.tuned.ui.LinkButton; -import net.sourceforge.tuned.ui.RoundBorder; +import net.sourceforge.filebot.util.ui.AbstractBean; +import net.sourceforge.filebot.util.ui.EmptySelectionModel; +import net.sourceforge.filebot.util.ui.LinkButton; +import net.sourceforge.filebot.util.ui.RoundBorder; class SubtitleAutoMatchDialog extends JDialog { diff --git a/source/net/sourceforge/filebot/ui/subtitle/SubtitleDownloadComponent.java b/source/net/sourceforge/filebot/ui/subtitle/SubtitleDownloadComponent.java index 71f023b3..6033556a 100644 --- a/source/net/sourceforge/filebot/ui/subtitle/SubtitleDownloadComponent.java +++ b/source/net/sourceforge/filebot/ui/subtitle/SubtitleDownloadComponent.java @@ -5,8 +5,8 @@ package net.sourceforge.filebot.ui.subtitle; import static net.sourceforge.filebot.MediaTypes.*; import static net.sourceforge.filebot.subtitle.SubtitleUtilities.*; import static net.sourceforge.filebot.ui.NotificationLogging.*; -import static net.sourceforge.tuned.FileUtilities.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; @@ -46,9 +46,9 @@ import net.sourceforge.filebot.subtitle.SubtitleFormat; import net.sourceforge.filebot.ui.subtitle.SubtitlePackage.Download.Phase; import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler; import net.sourceforge.filebot.vfs.MemoryFile; -import net.sourceforge.tuned.ExceptionUtilities; -import net.sourceforge.tuned.ui.ListView; -import net.sourceforge.tuned.ui.TunedUtilities; +import net.sourceforge.filebot.util.ExceptionUtilities; +import net.sourceforge.filebot.util.ui.ListView; +import net.sourceforge.filebot.util.ui.TunedUtilities; import ca.odell.glazedlists.BasicEventList; import ca.odell.glazedlists.EventList; import ca.odell.glazedlists.FilterList; diff --git a/source/net/sourceforge/filebot/ui/subtitle/SubtitleDropTarget.java b/source/net/sourceforge/filebot/ui/subtitle/SubtitleDropTarget.java index 33759470..d133551e 100644 --- a/source/net/sourceforge/filebot/ui/subtitle/SubtitleDropTarget.java +++ b/source/net/sourceforge/filebot/ui/subtitle/SubtitleDropTarget.java @@ -4,8 +4,8 @@ import static net.sourceforge.filebot.MediaTypes.*; import static net.sourceforge.filebot.media.MediaDetection.*; import static net.sourceforge.filebot.ui.NotificationLogging.*; import static net.sourceforge.filebot.ui.transfer.FileTransferable.*; -import static net.sourceforge.tuned.FileUtilities.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Color; import java.awt.Cursor; @@ -38,8 +38,8 @@ import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.web.OpenSubtitlesClient; import net.sourceforge.filebot.web.SubtitleProvider; import net.sourceforge.filebot.web.VideoHashSubtitleService; -import net.sourceforge.tuned.FileUtilities; -import net.sourceforge.tuned.FileUtilities.ParentFilter; +import net.sourceforge.filebot.util.FileUtilities; +import net.sourceforge.filebot.util.FileUtilities.ParentFilter; abstract class SubtitleDropTarget extends JButton { diff --git a/source/net/sourceforge/filebot/ui/subtitle/SubtitlePackage.java b/source/net/sourceforge/filebot/ui/subtitle/SubtitlePackage.java index 4848ce4d..b1da57ab 100644 --- a/source/net/sourceforge/filebot/ui/subtitle/SubtitlePackage.java +++ b/source/net/sourceforge/filebot/ui/subtitle/SubtitlePackage.java @@ -23,7 +23,7 @@ import net.sourceforge.filebot.vfs.ArchiveType; import net.sourceforge.filebot.vfs.MemoryFile; import net.sourceforge.filebot.web.SubtitleDescriptor; import net.sourceforge.filebot.web.SubtitleProvider; -import net.sourceforge.tuned.FileUtilities; +import net.sourceforge.filebot.util.FileUtilities; public class SubtitlePackage { diff --git a/source/net/sourceforge/filebot/ui/subtitle/SubtitlePackageCellRenderer.java b/source/net/sourceforge/filebot/ui/subtitle/SubtitlePackageCellRenderer.java index 816768e0..0f98adf2 100644 --- a/source/net/sourceforge/filebot/ui/subtitle/SubtitlePackageCellRenderer.java +++ b/source/net/sourceforge/filebot/ui/subtitle/SubtitlePackageCellRenderer.java @@ -12,8 +12,8 @@ import javax.swing.border.CompoundBorder; import net.miginfocom.swing.MigLayout; import net.sourceforge.filebot.ResourceManager; -import net.sourceforge.tuned.ui.AbstractFancyListCellRenderer; -import net.sourceforge.tuned.ui.DashedSeparator; +import net.sourceforge.filebot.util.ui.AbstractFancyListCellRenderer; +import net.sourceforge.filebot.util.ui.DashedSeparator; class SubtitlePackageCellRenderer extends AbstractFancyListCellRenderer { diff --git a/source/net/sourceforge/filebot/ui/subtitle/SubtitlePanel.java b/source/net/sourceforge/filebot/ui/subtitle/SubtitlePanel.java index 239104b5..fa0a6fb2 100644 --- a/source/net/sourceforge/filebot/ui/subtitle/SubtitlePanel.java +++ b/source/net/sourceforge/filebot/ui/subtitle/SubtitlePanel.java @@ -3,7 +3,7 @@ package net.sourceforge.filebot.ui.subtitle; import static net.sourceforge.filebot.Settings.*; import static net.sourceforge.filebot.ui.LanguageComboBoxModel.*; import static net.sourceforge.filebot.ui.NotificationLogging.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Color; import java.awt.Cursor; @@ -45,8 +45,8 @@ import net.sourceforge.filebot.web.SearchResult; import net.sourceforge.filebot.web.SubtitleDescriptor; import net.sourceforge.filebot.web.SubtitleProvider; import net.sourceforge.filebot.web.VideoHashSubtitleService; -import net.sourceforge.tuned.ui.LabelProvider; -import net.sourceforge.tuned.ui.SimpleLabelProvider; +import net.sourceforge.filebot.util.ui.LabelProvider; +import net.sourceforge.filebot.util.ui.SimpleLabelProvider; public class SubtitlePanel extends AbstractSearchPanel { diff --git a/source/net/sourceforge/filebot/ui/subtitle/SubtitleUploadDialog.java b/source/net/sourceforge/filebot/ui/subtitle/SubtitleUploadDialog.java index 2e8380c9..64867180 100644 --- a/source/net/sourceforge/filebot/ui/subtitle/SubtitleUploadDialog.java +++ b/source/net/sourceforge/filebot/ui/subtitle/SubtitleUploadDialog.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.ui.subtitle; import static net.sourceforge.filebot.MediaTypes.*; import static net.sourceforge.filebot.media.MediaDetection.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Color; import java.awt.Component; @@ -63,9 +63,9 @@ import net.sourceforge.filebot.web.SearchResult; import net.sourceforge.filebot.web.TheTVDBClient.SeriesInfo; import net.sourceforge.filebot.web.TheTVDBSearchResult; import net.sourceforge.filebot.web.VideoHashSubtitleService.CheckResult; -import net.sourceforge.tuned.FileUtilities; -import net.sourceforge.tuned.ui.AbstractBean; -import net.sourceforge.tuned.ui.EmptySelectionModel; +import net.sourceforge.filebot.util.FileUtilities; +import net.sourceforge.filebot.util.ui.AbstractBean; +import net.sourceforge.filebot.util.ui.EmptySelectionModel; public class SubtitleUploadDialog extends JDialog { diff --git a/source/net/sourceforge/filebot/ui/subtitle/SubtitleViewer.java b/source/net/sourceforge/filebot/ui/subtitle/SubtitleViewer.java index 2757a961..7d88b0c8 100644 --- a/source/net/sourceforge/filebot/ui/subtitle/SubtitleViewer.java +++ b/source/net/sourceforge/filebot/ui/subtitle/SubtitleViewer.java @@ -5,7 +5,7 @@ package net.sourceforge.filebot.ui.subtitle; import static java.awt.Font.*; import static java.util.Collections.*; import static java.util.regex.Pattern.*; -import static net.sourceforge.tuned.ui.TunedUtilities.*; +import static net.sourceforge.filebot.util.ui.TunedUtilities.*; import java.awt.Color; import java.awt.Component; @@ -47,10 +47,10 @@ import javax.swing.table.TableRowSorter; import net.miginfocom.swing.MigLayout; import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.subtitle.SubtitleElement; -import net.sourceforge.tuned.ui.GradientStyle; -import net.sourceforge.tuned.ui.LazyDocumentListener; -import net.sourceforge.tuned.ui.notification.SeparatorBorder; -import net.sourceforge.tuned.ui.notification.SeparatorBorder.Position; +import net.sourceforge.filebot.util.ui.GradientStyle; +import net.sourceforge.filebot.util.ui.LazyDocumentListener; +import net.sourceforge.filebot.util.ui.notification.SeparatorBorder; +import net.sourceforge.filebot.util.ui.notification.SeparatorBorder.Position; public class SubtitleViewer extends JFrame { diff --git a/source/net/sourceforge/filebot/ui/transfer/ByteBufferTransferable.java b/source/net/sourceforge/filebot/ui/transfer/ByteBufferTransferable.java index e4a1b40d..49049524 100644 --- a/source/net/sourceforge/filebot/ui/transfer/ByteBufferTransferable.java +++ b/source/net/sourceforge/filebot/ui/transfer/ByteBufferTransferable.java @@ -3,7 +3,7 @@ package net.sourceforge.filebot.ui.transfer; import static net.sourceforge.filebot.Settings.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; @@ -18,7 +18,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import net.sourceforge.tuned.TemporaryFolder; +import net.sourceforge.filebot.util.TemporaryFolder; public class ByteBufferTransferable implements Transferable { diff --git a/source/net/sourceforge/filebot/ui/transfer/FileTransferablePolicy.java b/source/net/sourceforge/filebot/ui/transfer/FileTransferablePolicy.java index 5ed21ec7..25584377 100644 --- a/source/net/sourceforge/filebot/ui/transfer/FileTransferablePolicy.java +++ b/source/net/sourceforge/filebot/ui/transfer/FileTransferablePolicy.java @@ -3,7 +3,7 @@ package net.sourceforge.filebot.ui.transfer; import static net.sourceforge.filebot.ui.transfer.FileTransferable.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; diff --git a/source/net/sourceforge/filebot/ui/transfer/SaveAction.java b/source/net/sourceforge/filebot/ui/transfer/SaveAction.java index 8dbd5e59..3b1aa22c 100644 --- a/source/net/sourceforge/filebot/ui/transfer/SaveAction.java +++ b/source/net/sourceforge/filebot/ui/transfer/SaveAction.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.ui.transfer; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.awt.event.ActionEvent; import java.io.File; diff --git a/source/net/sourceforge/filebot/util/ByteBufferInputStream.java b/source/net/sourceforge/filebot/util/ByteBufferInputStream.java new file mode 100644 index 00000000..1a5a932b --- /dev/null +++ b/source/net/sourceforge/filebot/util/ByteBufferInputStream.java @@ -0,0 +1,74 @@ + +package net.sourceforge.filebot.util; + + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; + + +public class ByteBufferInputStream extends InputStream { + + private final ByteBuffer buffer; + + + public ByteBufferInputStream(ByteBuffer buffer) { + this.buffer = buffer; + } + + + @Override + public int read() throws IOException { + return (buffer.position() < buffer.limit()) ? (buffer.get() & 0xff) : -1; + } + + + @Override + public int read(byte[] b, int off, int len) throws IOException { + if (b == null) { + throw new NullPointerException(); + } else if (off < 0 || len < 0 || len > b.length - off) { + throw new IndexOutOfBoundsException(); + } + + if (buffer.position() >= buffer.limit()) { + return -1; + } + + if (len > buffer.remaining()) { + len = buffer.remaining(); + } + + if (len <= 0) { + return 0; + } + + buffer.get(b, off, len); + return len; + } + + + @Override + public int available() throws IOException { + return buffer.remaining(); + } + + + @Override + public boolean markSupported() { + return true; + } + + + @Override + public void mark(int readlimit) { + buffer.mark(); + } + + + @Override + public void reset() throws IOException { + buffer.reset(); + } + +} diff --git a/source/net/sourceforge/filebot/util/ByteBufferOutputStream.java b/source/net/sourceforge/filebot/util/ByteBufferOutputStream.java new file mode 100644 index 00000000..5c6e905f --- /dev/null +++ b/source/net/sourceforge/filebot/util/ByteBufferOutputStream.java @@ -0,0 +1,131 @@ +package net.sourceforge.filebot.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; + +public class ByteBufferOutputStream extends OutputStream { + + private ByteBuffer buffer; + + private final float loadFactor; + + public ByteBufferOutputStream(long initialCapacity) { + this((int) initialCapacity); + } + + public ByteBufferOutputStream(int initialCapacity) { + this(initialCapacity, 1.0f); + } + + public ByteBufferOutputStream(int initialCapacity, float loadFactor) { + if (initialCapacity < 0) + throw new IllegalArgumentException("initialCapacity must not be negative"); + + if (loadFactor <= 0 || Float.isNaN(loadFactor)) + throw new IllegalArgumentException("loadFactor must be greater than 0"); + + this.buffer = ByteBuffer.allocate(initialCapacity + 1); + this.loadFactor = loadFactor; + } + + @Override + public void write(int b) throws IOException { + ensureCapacity(buffer.position() + 1); + buffer.put((byte) b); + } + + @Override + public void write(byte[] src) throws IOException { + ensureCapacity(buffer.position() + src.length); + buffer.put(src); + } + + public void write(ByteBuffer src) throws IOException { + ensureCapacity(buffer.position() + src.remaining()); + buffer.put(src); + } + + @Override + public void write(byte[] src, int offset, int length) throws IOException { + ensureCapacity(buffer.position() + length); + buffer.put(src, offset, length); + } + + public void ensureCapacity(int minCapacity) { + if (minCapacity <= buffer.capacity()) + return; + + // calculate new buffer size with load factor + int newCapacity = (int) (buffer.capacity() * (1 + loadFactor)); + + // ensure minCapacity + if (newCapacity < minCapacity) + newCapacity = minCapacity; + + // create new buffer with increased capacity + ByteBuffer newBuffer = ByteBuffer.allocate(newCapacity); + + // copy current data to new buffer + buffer.flip(); + newBuffer.put(buffer); + + buffer = newBuffer; + } + + public ByteBuffer getByteBuffer() { + ByteBuffer result = buffer.duplicate(); + + // flip buffer so it can be read + result.flip(); + + return result; + } + + public byte[] getByteArray() { + ByteBuffer data = getByteBuffer(); + + // copy data to byte array + byte[] bytes = new byte[data.remaining()]; + data.get(bytes); + + return bytes; + } + + public int transferFrom(ReadableByteChannel channel) throws IOException { + // make sure buffer is not at its limit + ensureCapacity(buffer.position() + 1); + + return channel.read(buffer); + } + + public int transferFully(InputStream inputStream) throws IOException { + return transferFully(Channels.newChannel(inputStream)); + } + + public int transferFully(ReadableByteChannel channel) throws IOException { + int total = 0, read = 0; + + while ((read = transferFrom(channel)) >= 0) { + total += read; + } + + return total; + } + + public int position() { + return buffer.position(); + } + + public int capacity() { + return buffer.capacity(); + } + + public void rewind() { + buffer.rewind(); + } + +} diff --git a/source/net/sourceforge/filebot/util/DefaultThreadFactory.java b/source/net/sourceforge/filebot/util/DefaultThreadFactory.java new file mode 100644 index 00000000..a37af384 --- /dev/null +++ b/source/net/sourceforge/filebot/util/DefaultThreadFactory.java @@ -0,0 +1,56 @@ + +package net.sourceforge.filebot.util; + + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + + +public class DefaultThreadFactory implements ThreadFactory { + + private final AtomicInteger threadNumber = new AtomicInteger(0); + private final ThreadGroup group; + + private final int priority; + private final boolean daemon; + + + public DefaultThreadFactory(String name) { + this(name, Thread.NORM_PRIORITY); + } + + + public DefaultThreadFactory(String name, int priority) { + this(name, priority, false); + } + + + public DefaultThreadFactory(String groupName, int priority, boolean daemon) { + SecurityManager sm = System.getSecurityManager(); + ThreadGroup parentGroup = (sm != null) ? sm.getThreadGroup() : Thread.currentThread().getThreadGroup(); + + this.group = new ThreadGroup(parentGroup, groupName); + + this.daemon = daemon; + this.priority = priority; + } + + + public Thread newThread(Runnable r) { + Thread thread = new Thread(group, r, String.format("%s-thread-%d", group.getName(), threadNumber.incrementAndGet())); + + if (daemon != thread.isDaemon()) + thread.setDaemon(daemon); + + if (priority != thread.getPriority()) + thread.setPriority(priority); + + return thread; + } + + + public ThreadGroup getThreadGroup() { + return group; + } + +} diff --git a/source/net/sourceforge/filebot/util/DownloadTask.java b/source/net/sourceforge/filebot/util/DownloadTask.java new file mode 100644 index 00000000..f71ce11b --- /dev/null +++ b/source/net/sourceforge/filebot/util/DownloadTask.java @@ -0,0 +1,168 @@ + +package net.sourceforge.filebot.util; + + +import static net.sourceforge.filebot.web.WebRequest.*; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.ByteBuffer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.swing.SwingWorker; + + +public class DownloadTask extends SwingWorker { + + public static final String DOWNLOAD_STATE = "download state"; + public static final String DOWNLOAD_PROGRESS = "download progress"; + + + public static enum DownloadState { + PENDING, CONNECTING, DOWNLOADING, DONE + } + + private URL url; + + private long contentLength = -1; + private DownloadState state = DownloadState.PENDING; + + private Map postParameters; + private Map requestHeaders; + private Map> responseHeaders; + + + public DownloadTask(URL url) { + this.url = url; + } + + + protected HttpURLConnection createConnection() throws Exception { + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + + if (requestHeaders != null) { + for (Entry entry : requestHeaders.entrySet()) { + connection.addRequestProperty(entry.getKey(), entry.getValue()); + } + } + + return connection; + } + + + @Override + protected ByteBuffer doInBackground() throws Exception { + setDownloadState(DownloadState.CONNECTING); + + HttpURLConnection connection = createConnection(); + + if (postParameters != null) { + ByteBuffer postData = Charset.forName("UTF-8").encode(encodeParameters(postParameters, true)); + + // add content type and content length headers + connection.addRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + connection.addRequestProperty("Content-Length", String.valueOf(postData.remaining())); + + connection.setRequestMethod("POST"); + connection.setDoOutput(true); + + // write post data + WritableByteChannel out = Channels.newChannel(connection.getOutputStream()); + out.write(postData); + out.close(); + } + + contentLength = connection.getContentLength(); + + responseHeaders = connection.getHeaderFields(); + + setDownloadState(DownloadState.DOWNLOADING); + + ReadableByteChannel in = Channels.newChannel(connection.getInputStream()); + ByteBufferOutputStream buffer = new ByteBufferOutputStream((int) (contentLength > 0 ? contentLength : 32 * 1024)); + + try { + while (!isCancelled() && ((buffer.transferFrom(in)) >= 0)) { + + firePropertyChange(DOWNLOAD_PROGRESS, null, buffer.position()); + + if (isContentLengthKnown()) { + setProgress((int) ((buffer.position() * 100) / contentLength)); + } + } + } catch (IOException e) { + // if the content length is not known in advance an IOException (Premature EOF) + // is always thrown after all the data has been read + if (isContentLengthKnown()) + throw e; + + } finally { + in.close(); + + // download either finished or an exception is thrown + setDownloadState(DownloadState.DONE); + } + + return buffer.getByteBuffer(); + } + + + protected void setDownloadState(DownloadState state) { + this.state = state; + firePropertyChange(DOWNLOAD_STATE, null, state); + } + + + public DownloadState getDownloadState() { + return state; + } + + + public URL getUrl() { + return url; + } + + + public boolean isContentLengthKnown() { + return contentLength >= 0; + } + + + public long getContentLength() { + return contentLength; + } + + + public void setRequestHeaders(Map requestHeaders) { + this.requestHeaders = new HashMap(requestHeaders); + } + + + public void setPostParameters(Map postParameters) { + this.postParameters = new HashMap(postParameters); + } + + + public Map> getResponseHeaders() { + return responseHeaders; + } + + + public Map getPostParameters() { + return postParameters; + } + + + public Map getRequestHeaders() { + return requestHeaders; + } + +} diff --git a/source/net/sourceforge/filebot/util/ExceptionUtilities.java b/source/net/sourceforge/filebot/util/ExceptionUtilities.java new file mode 100644 index 00000000..c903a4c9 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ExceptionUtilities.java @@ -0,0 +1,69 @@ + +package net.sourceforge.filebot.util; + + +public final class ExceptionUtilities { + + public static Throwable getRootCause(Throwable t) { + while (t.getCause() != null) { + t = t.getCause(); + } + + return t; + } + + + public static T findCause(Throwable t, Class type) { + while (t != null) { + if (type.isInstance(t)) + return type.cast(t); + + t = t.getCause(); + } + + return null; + } + + + public static String getRootCauseMessage(Throwable t) { + return getMessage(getRootCause(t)); + } + + + public static String getMessage(Throwable t) { + String message = t.getMessage(); + + if (message == null || message.isEmpty()) { + message = t.toString(); + } + + return message; + } + + + public static T wrap(Throwable t, Class type) { + if (type.isInstance(t)) { + return type.cast(t); + } + + try { + return type.getConstructor(Throwable.class).newInstance(t); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + + + public static RuntimeException asRuntimeException(Throwable t) { + return wrap(t, RuntimeException.class); + } + + + /** + * Dummy constructor to prevent instantiation. + */ + private ExceptionUtilities() { + throw new UnsupportedOperationException(); + } + +} diff --git a/source/net/sourceforge/filebot/util/FastFile.java b/source/net/sourceforge/filebot/util/FastFile.java new file mode 100644 index 00000000..76f4ba9c --- /dev/null +++ b/source/net/sourceforge/filebot/util/FastFile.java @@ -0,0 +1,64 @@ +package net.sourceforge.filebot.util; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class FastFile extends File { + + private Long length; + private Boolean isDirectory; + private Boolean isFile; + + public FastFile(String path) { + super(path); + } + + public FastFile(File parent, String child) { + super(parent, child); + } + + @Override + public long length() { + return length != null ? length : (length = super.length()); + } + + @Override + public boolean isDirectory() { + return isDirectory != null ? isDirectory : (isDirectory = super.isDirectory()); + } + + @Override + public boolean isFile() { + return isFile != null ? isFile : (isFile = super.isFile()); + } + + @Override + public File[] listFiles() { + String[] names = list(); + if (names == null) + return null; + + File[] files = new File[names.length]; + for (int i = 0; i < names.length; i++) { + files[i] = new FastFile(this, names[i]); + } + return files; + } + + public static FastFile get(File file) { + return new FastFile(file.getPath()); + } + + public static List get(Collection files) { + List result = new ArrayList(files.size()); + + for (File file : files) { + result.add(new FastFile(file.getPath())); + } + + return result; + } + +} diff --git a/source/net/sourceforge/filebot/util/FileUtilities.java b/source/net/sourceforge/filebot/util/FileUtilities.java new file mode 100644 index 00000000..d2a27bf9 --- /dev/null +++ b/source/net/sourceforge/filebot/util/FileUtilities.java @@ -0,0 +1,693 @@ +package net.sourceforge.filebot.util; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringWriter; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.charset.Charset; +import java.nio.file.AtomicMoveNotSupportedException; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Scanner; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.w3c.dom.Document; + +import com.ibm.icu.text.CharsetDetector; +import com.ibm.icu.text.CharsetMatch; + +public final class FileUtilities { + + public static File moveRename(File source, File destination) throws IOException { + // resolve destination + destination = resolveDestination(source, destination, true); + + if (source.isDirectory()) { + // move folder + org.apache.commons.io.FileUtils.moveDirectory(source, destination); + } else { + // on Windows ATOMIC_MOVE allows us to rename files even if only lower/upper-case changes (without ATOMIC_MOVE the operation would be ignored) + try { + java.nio.file.Files.move(source.toPath(), destination.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE); + } catch (AtomicMoveNotSupportedException e) { + java.nio.file.Files.move(source.toPath(), destination.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + } + + return destination; + } + + public static File copyAs(File source, File destination) throws IOException { + // resolve destination + destination = resolveDestination(source, destination, true); + + if (source.isDirectory()) { + // copy folder + org.apache.commons.io.FileUtils.copyDirectory(source, destination); + } else { + // copy file + java.nio.file.Files.copy(source.toPath(), destination.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + + return destination; + } + + public static File resolveDestination(File source, File destination, boolean mkdirs) throws IOException { + // resolve destination + if (!destination.isAbsolute()) { + // same folder, different name + destination = new File(source.getParentFile(), destination.getPath()); + } + + // make sure we that we can create the destination folder structure + File destinationFolder = destination.getParentFile(); + + // create parent folder if necessary + if (mkdirs && !destinationFolder.isDirectory() && !destinationFolder.mkdirs()) { + throw new IOException("Failed to create folder: " + destinationFolder); + } + + return destination; + } + + public static File createRelativeSymlink(File link, File target, boolean relativize) throws IOException { + if (relativize) { + // make sure we're working with the full path + link = link.getCanonicalFile(); + target = target.getCanonicalFile(); + + try { + target = link.getParentFile().toPath().relativize(target.toPath()).toFile(); + } catch (Throwable e) { + // unable to relativize link target + } + } + + // create symlink via NIO.2 + return java.nio.file.Files.createSymbolicLink(link.toPath(), target.toPath()).toFile(); + } + + public static boolean delete(File file) { + // delete files or files + return org.apache.commons.io.FileUtils.deleteQuietly(file); + } + + public static byte[] readFile(File source) throws IOException { + InputStream in = new FileInputStream(source); + + try { + long size = source.length(); + if (size < 0 || size > Integer.MAX_VALUE) { + throw new IllegalArgumentException("Unable to read file: " + source); + } + + byte[] data = new byte[(int) size]; + + int position = 0; + int read = 0; + + while (position < data.length && (read = in.read(data, position, data.length - position)) >= 0) { + position += read; + } + + return data; + } finally { + in.close(); + } + } + + public static String readAll(Reader source) throws IOException { + StringBuilder text = new StringBuilder(); + char[] buffer = new char[2048]; + + int read = 0; + while ((read = source.read(buffer)) >= 0) { + text.append(buffer, 0, read); + } + + return text.toString(); + } + + public static void writeFile(ByteBuffer data, File destination) throws IOException { + FileChannel fileChannel = new FileOutputStream(destination).getChannel(); + + try { + fileChannel.write(data); + } finally { + fileChannel.close(); + } + } + + public static List readCSV(InputStream source, String charsetName, String separatorPattern) { + Scanner scanner = new Scanner(source, charsetName); + Pattern separator = Pattern.compile(separatorPattern); + List rows = new ArrayList(65536); + + while (scanner.hasNextLine()) { + rows.add(separator.split(scanner.nextLine())); + } + + return rows; + } + + public static Reader createTextReader(File file) throws IOException { + CharsetDetector detector = new CharsetDetector(); + detector.setDeclaredEncoding("UTF-8"); // small boost for UTF-8 as default encoding + detector.setText(new BufferedInputStream(new FileInputStream(file))); + + CharsetMatch charset = detector.detect(); + if (charset != null) + return charset.getReader(); + + // assume UTF-8 by default + return new InputStreamReader(new FileInputStream(file), "UTF-8"); + } + + public static String getText(ByteBuffer data) throws IOException { + CharsetDetector detector = new CharsetDetector(); + detector.setDeclaredEncoding("UTF-8"); // small boost for UTF-8 as default encoding + detector.setText(new ByteBufferInputStream(data)); + + CharsetMatch charset = detector.detect(); + if (charset != null) { + try { + return charset.getString(); + } catch (RuntimeException e) { + throw new IOException("Failed to read text", e); + } + } + + // assume UTF-8 by default + return Charset.forName("UTF-8").decode(data).toString(); + } + + /** + * Pattern used for matching file extensions. + * + * e.g. "file.txt" -> match "txt", ".hidden" -> no match + */ + public static final Pattern EXTENSION = Pattern.compile("(?<=.[.])\\p{Alnum}+$"); + public static final String UNC_PREFIX = "\\\\"; + + public static String getExtension(File file) { + if (file.isDirectory()) + return null; + + return getExtension(file.getName()); + } + + public static String getExtension(String name) { + Matcher matcher = EXTENSION.matcher(name); + + if (matcher.find()) { + // extension without leading '.' + return matcher.group(); + } + + // no extension + return null; + } + + public static boolean hasExtension(File file, String... extensions) { + // avoid native call for speed, if possible + return hasExtension(file.getName(), extensions) && !file.isDirectory(); + } + + public static boolean hasExtension(String filename, String... extensions) { + for (String it : extensions) { + if (filename.length() - it.length() >= 2 && filename.charAt(filename.length() - it.length() - 1) == '.') { + String tail = filename.substring(filename.length() - it.length(), filename.length()); + if (tail.equalsIgnoreCase(it)) { + return true; + } + } + } + + return false; + } + + public static String getNameWithoutExtension(String name) { + Matcher matcher = EXTENSION.matcher(name); + + if (matcher.find()) { + return name.substring(0, matcher.start() - 1); + } + + // no extension, return given name + return name; + } + + public static String getName(File file) { + if (file.getName().isEmpty() || UNC_PREFIX.equals(file.getParent())) + return getFolderName(file); + + return getNameWithoutExtension(file.getName()); + } + + public static String getFolderName(File file) { + if (UNC_PREFIX.equals(file.getParent())) + return file.toString(); + + if (file.getName().length() > 0) + return file.getName(); + + // file might be a drive (only has a path, but no name) + return replacePathSeparators(file.toString(), ""); + } + + public static boolean isDerived(File derivate, File prime) { + return isDerived(getName(derivate), prime); + } + + public static boolean isDerived(String derivate, File prime) { + String base = getName(prime).trim().toLowerCase(); + derivate = derivate.trim().toLowerCase(); + return derivate.startsWith(base); + } + + public static boolean isDerivedByExtension(File derivate, File prime) { + return isDerivedByExtension(getName(derivate), prime); + } + + public static boolean isDerivedByExtension(String derivate, File prime) { + String base = getName(prime).trim().toLowerCase(); + derivate = derivate.trim().toLowerCase(); + + if (derivate.equals(base)) + return true; + + while (derivate.length() > base.length() && getExtension(derivate) != null) { + derivate = getNameWithoutExtension(derivate); + + if (derivate.equals(base)) + return true; + } + + return false; + } + + public static boolean containsOnly(Collection files, FileFilter filter) { + if (files.isEmpty()) { + return false; + } + for (File file : files) { + if (!filter.accept(file)) + return false; + } + return true; + } + + public static List sortByUniquePath(Collection files) { + // sort by unique lower-case paths + TreeSet sortedSet = new TreeSet(CASE_INSENSITIVE_PATH); + sortedSet.addAll(files); + + return new ArrayList(sortedSet); + } + + public static List filter(Iterable files, FileFilter... filters) { + List accepted = new ArrayList(); + + for (File file : files) { + for (FileFilter filter : filters) { + if (filter.accept(file)) { + accepted.add(file); + break; + } + } + } + + return accepted; + } + + public static FileFilter not(FileFilter filter) { + return new NotFileFilter(filter); + } + + public static List flatten(Iterable roots, int maxDepth, boolean listHiddenFiles) { + List files = new ArrayList(); + + // unfold/flatten file tree + for (File root : roots) { + if (root.isDirectory()) { + listFiles(root, 0, files, maxDepth, listHiddenFiles); + } else { + files.add(root); + } + } + + return files; + } + + public static List listPath(File file) { + return listPathTail(file, Integer.MAX_VALUE, false); + } + + public static List listPathTail(File file, int tailSize, boolean reverse) { + LinkedList nodes = new LinkedList(); + + File node = file; + for (int i = 0; node != null && i < tailSize && !UNC_PREFIX.equals(node.toString()); i++, node = node.getParentFile()) { + if (reverse) { + nodes.addLast(node); + } else { + nodes.addFirst(node); + } + } + + return nodes; + } + + public static File getRelativePathTail(File file, int tailSize) { + File f = null; + for (File it : listPathTail(file, tailSize, false)) { + if (it.getParentFile() != null) { + f = new File(f, it.getName()); + } + } + return f; + } + + public static List listFiles(Iterable folders, int maxDepth, boolean listHiddenFiles) { + List files = new ArrayList(); + + // collect files from directory tree + for (File folder : folders) { + listFiles(folder, 0, files, maxDepth, listHiddenFiles); + } + + return files; + } + + private static void listFiles(File folder, int depth, List files, int maxDepth, boolean listHiddenFiles) { + if (depth > maxDepth) + return; + + File[] children = folder.listFiles(); + if (children == null) + return; + + for (File file : children) { + if (!listHiddenFiles && file.isHidden()) // ignore hidden files + continue; + + if (file.isDirectory()) { + listFiles(file, depth + 1, files, maxDepth, listHiddenFiles); + } else { + files.add(file); + } + } + } + + public static SortedMap> mapByFolder(Iterable files) { + SortedMap> map = new TreeMap>(); + + for (File file : files) { + File key = file.getParentFile(); + if (key == null) { + throw new IllegalArgumentException("Parent is null: " + file); + } + + List valueList = map.get(key); + if (valueList == null) { + valueList = new ArrayList(); + map.put(key, valueList); + } + + valueList.add(file); + } + + return map; + } + + public static Map> mapByExtension(Iterable files) { + Map> map = new HashMap>(); + + for (File file : files) { + String key = getExtension(file); + if (key != null) { + key = key.toLowerCase(); + } + + List valueList = map.get(key); + if (valueList == null) { + valueList = new ArrayList(); + map.put(key, valueList); + } + + valueList.add(file); + } + + return map; + } + + /** + * Invalid file name characters: \, /, :, *, ?, ", <, >, |, \r and \n + */ + public static final Pattern ILLEGAL_CHARACTERS = Pattern.compile("[\\\\/:*?\"<>|\\r\\n]|[ ]+$|(?<=[^.])[.]+$"); + + /** + * Strip file name of invalid characters + * + * @param filename + * original filename + * @return valid file name stripped of invalid characters + */ + public static String validateFileName(CharSequence filename) { + // strip invalid characters from file name + return ILLEGAL_CHARACTERS.matcher(filename).replaceAll("").replaceAll("\\s+", " ").trim(); + } + + public static boolean isInvalidFileName(CharSequence filename) { + // check if file name contains any illegal characters + return ILLEGAL_CHARACTERS.matcher(filename).find(); + } + + public static File validateFileName(File file) { + // windows drives (e.g. c:, d:, etc.) are never invalid because name will be an empty string + if (!isInvalidFileName(file.getName())) + return file; + + // validate file name only + return new File(file.getParentFile(), validateFileName(file.getName())); + } + + public static File validateFilePath(File path) { + Iterator nodes = listPath(path).iterator(); + + // initialize with root node, keep original root object if possible (so we don't loose the drive on windows) + File validatedPath = validateFileName(nodes.next()); + + // validate the rest of the path + while (nodes.hasNext()) { + validatedPath = new File(validatedPath, validateFileName(nodes.next().getName())); + } + + return validatedPath; + } + + public static boolean isInvalidFilePath(File path) { + // check if file name contains any illegal characters + for (File node = path; node != null; node = node.getParentFile()) { + if (isInvalidFileName(node.getName())) + return true; + } + + return false; + } + + public static String normalizePathSeparators(String path) { + // special handling for UNC paths + if (path.startsWith(UNC_PREFIX) && path.length() > 2) { + return UNC_PREFIX + path.substring(2).replace('\\', '/'); + } + return path.replace('\\', '/'); + } + + public static String replacePathSeparators(CharSequence path) { + return replacePathSeparators(path, " "); + } + + public static String replacePathSeparators(CharSequence path, String replacement) { + return Pattern.compile("\\s*[\\\\/]+\\s*").matcher(path).replaceAll(replacement); + } + + public static String getXmlString(Document dom) throws TransformerException { + Transformer tr = TransformerFactory.newInstance().newTransformer(); + tr.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + tr.setOutputProperty(OutputKeys.INDENT, "yes"); + + // create string from dom + StringWriter buffer = new StringWriter(); + tr.transform(new DOMSource(dom), new StreamResult(buffer)); + return buffer.toString(); + } + + public static final long KILO = 1024; + public static final long MEGA = 1024 * KILO; + public static final long GIGA = 1024 * MEGA; + + public static String formatSize(long size) { + if (size >= MEGA) + return String.format("%,d MB", size / MEGA); + else if (size >= KILO) + return String.format("%,d KB", size / KILO); + else + return String.format("%,d Byte", size); + } + + public static final FileFilter FOLDERS = new FileFilter() { + + @Override + public boolean accept(File file) { + return file.isDirectory(); + } + }; + + public static final FileFilter FILES = new FileFilter() { + + @Override + public boolean accept(File file) { + return file.isFile(); + } + }; + + public static final FileFilter TEMPORARY = new FileFilter() { + + private final String tmpdir = System.getProperty("java.io.tmpdir"); + + @Override + public boolean accept(File file) { + return file.getAbsolutePath().startsWith(tmpdir); + } + }; + + public static class ParentFilter implements FileFilter { + + private final File folder; + + public ParentFilter(File folder) { + this.folder = folder; + } + + @Override + public boolean accept(File file) { + return listPath(file).contains(folder); + } + } + + public static class ExtensionFileFilter implements FileFilter { + + private final String[] extensions; + + public ExtensionFileFilter(String... extensions) { + this.extensions = extensions; + } + + public ExtensionFileFilter(Collection extensions) { + this.extensions = extensions.toArray(new String[0]); + } + + @Override + public boolean accept(File file) { + return hasExtension(file, extensions); + } + + public boolean accept(String name) { + return hasExtension(name, extensions); + } + + public boolean acceptExtension(String extension) { + for (String other : extensions) { + if (other.equalsIgnoreCase(extension)) + return true; + } + + return false; + } + + public String extension() { + return extensions[0]; + } + + public String[] extensions() { + return extensions.clone(); + } + } + + public static class RegexFileFilter implements FileFilter, FilenameFilter { + + private final Pattern pattern; + + public RegexFileFilter(Pattern pattern) { + this.pattern = pattern; + } + + @Override + public boolean accept(File dir, String name) { + return pattern.matcher(name).find(); + } + + @Override + public boolean accept(File file) { + return accept(file.getParentFile(), file.getName()); + } + } + + public static class NotFileFilter implements FileFilter { + + public FileFilter filter; + + public NotFileFilter(FileFilter filter) { + this.filter = filter; + } + + @Override + public boolean accept(File file) { + return !filter.accept(file); + } + } + + public static final Comparator CASE_INSENSITIVE_PATH = new Comparator() { + + @Override + public int compare(File o1, File o2) { + return o1.getPath().compareToIgnoreCase(o2.getPath()); + } + }; + + /** + * Dummy constructor to prevent instantiation. + */ + private FileUtilities() { + throw new UnsupportedOperationException(); + } + +} diff --git a/source/net/sourceforge/filebot/util/FilterIterator.java b/source/net/sourceforge/filebot/util/FilterIterator.java new file mode 100644 index 00000000..4571c81e --- /dev/null +++ b/source/net/sourceforge/filebot/util/FilterIterator.java @@ -0,0 +1,58 @@ + +package net.sourceforge.filebot.util; + + +import java.util.Iterator; + + +public abstract class FilterIterator implements Iterator { + + private final Iterator sourceIterator; + + + public FilterIterator(Iterable source) { + this(source.iterator()); + } + + + public FilterIterator(Iterator sourceIterator) { + this.sourceIterator = sourceIterator; + } + + + @Override + public boolean hasNext() { + return peekNext(false) != null; + } + + + @Override + public T next() { + try { + return peekNext(true); + } finally { + current = null; + } + } + + private T current = null; + + + private T peekNext(boolean forceNext) { + while (current == null && (forceNext || (sourceIterator.hasNext()))) { + current = filter(sourceIterator.next()); + } + + return current; + } + + + protected abstract T filter(S sourceValue); + + + @Override + public void remove() { + sourceIterator.remove(); + } + +} diff --git a/source/net/sourceforge/filebot/util/ListChangeSynchronizer.java b/source/net/sourceforge/filebot/util/ListChangeSynchronizer.java new file mode 100644 index 00000000..9e7dfba7 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ListChangeSynchronizer.java @@ -0,0 +1,50 @@ + +package net.sourceforge.filebot.util; + + +import java.util.List; + +import ca.odell.glazedlists.EventList; +import ca.odell.glazedlists.event.ListEvent; +import ca.odell.glazedlists.event.ListEventListener; + + +public class ListChangeSynchronizer implements ListEventListener { + + private final List target; + + + public ListChangeSynchronizer(EventList source, List target) { + this.target = target; + source.addListEventListener(this); + } + + + public void listChanged(ListEvent listChanges) { + EventList source = listChanges.getSourceList(); + + // update target list + while (listChanges.next()) { + int index = listChanges.getIndex(); + int type = listChanges.getType(); + + switch (type) { + case ListEvent.INSERT: + target.add(index, source.get(index)); + break; + case ListEvent.UPDATE: + target.set(index, source.get(index)); + break; + case ListEvent.DELETE: + target.remove(index); + break; + } + } + } + + + public static ListChangeSynchronizer syncEventListToList(EventList source, List target) { + return new ListChangeSynchronizer(source, target); + } + +} diff --git a/source/net/sourceforge/filebot/util/PreferencesList.java b/source/net/sourceforge/filebot/util/PreferencesList.java new file mode 100644 index 00000000..fff55d83 --- /dev/null +++ b/source/net/sourceforge/filebot/util/PreferencesList.java @@ -0,0 +1,136 @@ + +package net.sourceforge.filebot.util; + + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.RandomAccess; +import java.util.prefs.Preferences; + +import net.sourceforge.filebot.util.PreferencesMap.Adapter; + + +public class PreferencesList extends AbstractList implements RandomAccess { + + private final PreferencesMap prefs; + + + public PreferencesList(PreferencesMap preferencesMap) { + this.prefs = preferencesMap; + } + + + @Override + public T get(int index) { + return prefs.get(key(index)); + } + + + private String key(int index) { + return Integer.toString(index); + } + + + @Override + public int size() { + return prefs.size(); + } + + + @Override + public boolean add(T e) { + setImpl(size(), e); + return true; + } + + + @Override + public void add(int index, T element) { + int size = size(); + + if (index > size) + throw new IndexOutOfBoundsException(String.format("Index: %d, Size: %d", index, size)); + + copy(index, index + 1, size - index); + + setImpl(index, element); + } + + + private T setImpl(int index, T element) { + return prefs.put(key(index), element); + } + + + /** + * @return always null + */ + @Override + public T remove(int index) { + int lastIndex = size() - 1; + + copy(index + 1, index, lastIndex - index); + prefs.remove(key(lastIndex)); + + return null; + } + + + @Override + public T set(int index, T element) { + if (index < 0 || index >= size()) + throw new IndexOutOfBoundsException(); + + return setImpl(index, element); + } + + + private void copy(int startIndex, int newStartIndex, int count) { + if (count == 0 || startIndex == newStartIndex) + return; + + List copy = new ArrayList(subList(startIndex, startIndex + count)); + + for (int i = newStartIndex, n = 0; n < count; i++, n++) { + setImpl(i, copy.get(n)); + } + } + + + public void trimToSize(int limit) { + for (int i = size() - 1; i >= limit; i--) { + remove(i); + } + } + + + public void set(Collection data) { + // remove all elements beyond data.size + trimToSize(data.size()); + + // override elements + int i = 0; + for (T element : data) { + setImpl(i++, element); + } + } + + + @Override + public void clear() { + prefs.clear(); + } + + + public static PreferencesList map(Preferences prefs) { + return new PreferencesList(PreferencesMap.map(prefs)); + } + + + public static PreferencesList map(Preferences prefs, Adapter adapter) { + return new PreferencesList(PreferencesMap.map(prefs, adapter)); + } + +} diff --git a/source/net/sourceforge/filebot/util/PreferencesMap.java b/source/net/sourceforge/filebot/util/PreferencesMap.java new file mode 100644 index 00000000..0f9383af --- /dev/null +++ b/source/net/sourceforge/filebot/util/PreferencesMap.java @@ -0,0 +1,347 @@ + +package net.sourceforge.filebot.util; + + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.prefs.BackingStoreException; +import java.util.prefs.Preferences; + + +public class PreferencesMap implements Map { + + private final Preferences prefs; + private final Adapter adapter; + + + public PreferencesMap(Preferences prefs, Adapter adapter) { + this.prefs = prefs; + this.adapter = adapter; + } + + + @Override + public T get(Object key) { + return adapter.get(prefs, key.toString()); + } + + + @Override + public T put(String key, T value) { + adapter.put(prefs, key, value); + + // don't know previous entry + return null; + } + + + @Override + public T remove(Object key) { + adapter.remove(prefs, key.toString()); + + // don't know removed entry + return null; + } + + + public String[] keys() { + try { + return adapter.keys(prefs); + } catch (BackingStoreException e) { + throw new RuntimeException(e); + } + } + + + @Override + public void clear() { + for (String key : keys()) { + adapter.remove(prefs, key); + } + } + + + @Override + public boolean containsKey(Object key) { + if (key instanceof String) { + return Arrays.asList(keys()).contains(key); + } + + return false; + } + + + @Override + public boolean containsValue(Object value) { + for (String key : keys()) { + if (value.equals(get(key))) + return true; + } + + return false; + } + + + @Override + public Set> entrySet() { + Set> entries = new LinkedHashSet>(); + + for (String key : keys()) { + entries.add(new PreferencesEntry(prefs, key, adapter)); + } + + return entries; + } + + + @Override + public boolean isEmpty() { + return size() == 0; + } + + + @Override + public Set keySet() { + return new LinkedHashSet(Arrays.asList(keys())); + } + + + @Override + public void putAll(Map map) { + for (Map.Entry entry : map.entrySet()) { + put(entry.getKey(), entry.getValue()); + } + } + + + @Override + public int size() { + return keys().length; + } + + + @Override + public Collection values() { + List values = new ArrayList(); + + for (String key : keys()) { + values.add(get(key)); + } + + return values; + } + + + public static PreferencesMap map(Preferences prefs) { + return map(prefs, new StringAdapter()); + } + + + public static PreferencesMap map(Preferences prefs, Adapter adapter) { + return new PreferencesMap(prefs, adapter); + } + + + public static interface Adapter { + + public String[] keys(Preferences prefs) throws BackingStoreException; + + + public T get(Preferences prefs, String key); + + + public void put(Preferences prefs, String key, T value); + + + public void remove(Preferences prefs, String key); + } + + + public static abstract class AbstractAdapter implements Adapter { + + @Override + public abstract T get(Preferences prefs, String key); + + + @Override + public abstract void put(Preferences prefs, String key, T value); + + + @Override + public String[] keys(Preferences prefs) throws BackingStoreException { + return prefs.keys(); + } + + + @Override + public void remove(Preferences prefs, String key) { + prefs.remove(key); + } + + } + + + public static class StringAdapter extends AbstractAdapter { + + @Override + public String get(Preferences prefs, String key) { + return prefs.get(key, null); + } + + + @Override + public void put(Preferences prefs, String key, String value) { + prefs.put(key, value); + } + + } + + + public static class SimpleAdapter extends AbstractAdapter { + + private final Constructor constructor; + + + public SimpleAdapter(Class type) { + try { + constructor = type.getConstructor(String.class); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + + + @Override + public T get(Preferences prefs, String key) { + String value = prefs.get(key, null); + + if (value != null) { + try { + return constructor.newInstance(value); + } catch (InvocationTargetException e) { + // try to throw the cause directly, e.g. NumberFormatException + throw ExceptionUtilities.asRuntimeException(e.getCause()); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + return null; + } + + + @Override + public void put(Preferences prefs, String key, T value) { + prefs.put(key, value.toString()); + } + + + public static SimpleAdapter forClass(Class type) { + return new SimpleAdapter(type); + } + + } + + + public static class SerializableAdapter extends AbstractAdapter { + + @SuppressWarnings("unchecked") + @Override + public T get(Preferences prefs, String key) { + byte[] bytes = prefs.getByteArray(key, null); + + if (bytes == null) + return null; + + try { + ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes)); + Object object = in.readObject(); + in.close(); + + return (T) object; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + + @Override + public void put(Preferences prefs, String key, T value) { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + try { + ObjectOutputStream out = new ObjectOutputStream(buffer); + out.writeObject(value); + out.close(); + + prefs.putByteArray(key, buffer.toByteArray()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + + public static class PreferencesEntry implements Entry { + + private final String key; + + private final Preferences prefs; + + private final Adapter adapter; + + private T defaultValue = null; + + + public PreferencesEntry(Preferences prefs, String key, Adapter adapter) { + this.key = key; + this.prefs = prefs; + this.adapter = adapter; + } + + + @Override + public String getKey() { + return key; + } + + + @Override + public T getValue() { + T value = adapter.get(prefs, key); + return value != null ? value : defaultValue; + } + + + @Override + public T setValue(T value) { + adapter.put(prefs, key, value); + return null; + } + + + public PreferencesEntry defaultValue(T defaultValue) { + this.defaultValue = defaultValue; + return this; + } + + + public void remove() { + adapter.remove(prefs, key); + } + } + +} diff --git a/source/net/sourceforge/filebot/util/StringUtilities.java b/source/net/sourceforge/filebot/util/StringUtilities.java new file mode 100644 index 00000000..694cccac --- /dev/null +++ b/source/net/sourceforge/filebot/util/StringUtilities.java @@ -0,0 +1,52 @@ + +package net.sourceforge.filebot.util; + + +import static java.util.Arrays.*; + +import java.util.Iterator; + + +public final class StringUtilities { + + public static boolean isEmptyValue(Object object) { + return object == null || object.toString().length() == 0; + } + + + public static String joinBy(CharSequence delimiter, Object... values) { + return join(asList(values), delimiter); + } + + + public static String join(Object[] values, CharSequence delimiter) { + return join(asList(values), delimiter); + } + + + public static String join(Iterable values, CharSequence delimiter) { + StringBuilder sb = new StringBuilder(); + + for (Iterator iterator = values.iterator(); iterator.hasNext();) { + Object value = iterator.next(); + if (!isEmptyValue(value)) { + if (sb.length() > 0) { + sb.append(delimiter); + } + + sb.append(value); + } + } + + return sb.toString(); + } + + + /** + * Dummy constructor to prevent instantiation. + */ + private StringUtilities() { + throw new UnsupportedOperationException(); + } + +} diff --git a/source/net/sourceforge/filebot/util/TeePrintStream.java b/source/net/sourceforge/filebot/util/TeePrintStream.java new file mode 100644 index 00000000..3bf5b878 --- /dev/null +++ b/source/net/sourceforge/filebot/util/TeePrintStream.java @@ -0,0 +1,56 @@ + +package net.sourceforge.filebot.util; + + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; + + +public class TeePrintStream extends PrintStream { + + private final PrintStream cc; + + + public TeePrintStream(OutputStream out, boolean autoFlush, String encoding, PrintStream cc) throws UnsupportedEncodingException { + super(out, autoFlush, encoding); + this.cc = cc; + } + + + @Override + public void close() { + super.close(); + cc.close(); + } + + + @Override + public void flush() { + super.flush(); + cc.flush(); + } + + + @Override + public void write(byte[] buf, int off, int len) { + super.write(buf, off, len); + cc.write(buf, off, len); + } + + + @Override + public void write(int b) { + super.write(b); + cc.write(b); + } + + + @Override + public void write(byte[] b) throws IOException { + super.write(b); + cc.write(b); + } + +} diff --git a/source/net/sourceforge/filebot/util/TemporaryFolder.java b/source/net/sourceforge/filebot/util/TemporaryFolder.java new file mode 100644 index 00000000..f1c7189a --- /dev/null +++ b/source/net/sourceforge/filebot/util/TemporaryFolder.java @@ -0,0 +1,176 @@ + +package net.sourceforge.filebot.util; + + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + + +public final class TemporaryFolder { + + private static final Map folders = new HashMap(); + + + /** + * Get a {@link TemporaryFolder} instance for a given name. The actual directory will be + * created lazily (e.g. when a file is created). The name of the directory will start with + * the given name (lower-case) and contain a unique id, so multiple application instances + * may run at the same time without the risk of interference. + * + * @param name case-insensitive name of a temporary folder (e.g. application name) + * @return temporary folder for this name + */ + public static TemporaryFolder getFolder(String name) { + // make name case-insensitive + name = name.toLowerCase(); + + synchronized (folders) { + TemporaryFolder folder = folders.get(name); + + if (folder == null) { + File tmpdir = new File(System.getProperty("java.io.tmpdir")); + String subdir = String.format("%s [%s]", name, UUID.randomUUID()); + + folder = new TemporaryFolder(new File(tmpdir, subdir)); + folders.put(name, folder); + } + + return folder; + } + } + + + /** + * Delete all temporary folders on shutdown + */ + static { + Runtime.getRuntime().addShutdownHook(new Thread("TemporaryFolder Cleanup") { + + @Override + public void run() { + synchronized (folders) { + for (TemporaryFolder folder : folders.values()) { + folder.delete(); + } + } + } + }); + } + + private final File root; + + + private TemporaryFolder(File root) { + this.root = root; + } + + + /** + * Create an empty file in this temporary folder. + * + * @param name name of the file + * @return newly created file + * @throws IOException if an I/O error occurred + */ + public File createFile(String name) throws IOException { + + // if the directory does not exist it will be created + File file = new File(getFolder(), name); + file.createNewFile(); + + return file; + } + + + /** + * Creates an empty file in this temporary folder, using the given prefix and suffix to + * generate its name. + * + * @param prefix The prefix string to be used in generating the file's name; must be at + * least three characters long + * @param suffix The suffix string to be used in generating the file's name; may be null, + * in which case the suffix ".tmp" will be used + * @return An abstract pathname denoting a newly-created empty file + * @throws IOException If a file could not be created + * @see File#createTempFile(String, String) + */ + public File createFile(String prefix, String suffix) throws IOException { + return File.createTempFile(prefix, suffix, getFolder()); + } + + + public boolean deleteFile(String name) { + return new File(getFolder(), name).delete(); + } + + + /** + * Retrieve the {@link File} object for this {@link TemporaryFolder}. The actual directory + * for the {@link TemporaryFolder} instance will be created by this method. + * + * @return the {@link File} object for this {@link TemporaryFolder} + */ + public File getFolder() { + if (!root.exists()) { + root.mkdirs(); + } + + return root; + } + + + public TemporaryFolder subFolder(String name) { + return new TemporaryFolder(new File(getFolder(), name)); + } + + + public List list(boolean recursive) { + List list = new ArrayList(); + + list(root, list, recursive); + + return list; + } + + + private void list(File file, List list, boolean recursive) { + if (file.isDirectory()) { + for (File entry : file.listFiles()) { + if (entry.isDirectory()) { + if (recursive) { + list(entry, list, recursive); + } + } else { + list.add(entry); + } + } + } + } + + + public void delete() { + delete(root); + } + + + /** + * Delete files/folders recursively + * + * @param file file/folder that will be deleted + */ + private void delete(File file) { + if (file.isDirectory()) { + for (File entry : file.listFiles()) { + delete(entry); + } + } + + file.delete(); + } + +} diff --git a/source/net/sourceforge/filebot/util/Timer.java b/source/net/sourceforge/filebot/util/Timer.java new file mode 100644 index 00000000..01f0d6be --- /dev/null +++ b/source/net/sourceforge/filebot/util/Timer.java @@ -0,0 +1,95 @@ +package net.sourceforge.filebot.util; + +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; + +public abstract class Timer implements Runnable { + + private final ThreadFactory threadFactory = new DefaultThreadFactory("Timer", Thread.NORM_PRIORITY, true); + + private ScheduledThreadPoolExecutor executor; + private ScheduledFuture scheduledFuture; + private Thread shutdownHook; + + public synchronized void set(long delay, TimeUnit unit, boolean runBeforeShutdown) { + // create executor if necessary + if (executor == null) { + executor = new ScheduledThreadPoolExecutor(1, threadFactory); + } + + // cancel existing future task + if (scheduledFuture != null) { + scheduledFuture.cancel(true); + } + + Runnable runnable = this; + + if (runBeforeShutdown) { + try { + addShutdownHook(); + } catch (Exception e) { + // may fail if running with restricted permissions + Logger.getLogger(getClass().getName()).log(Level.WARNING, e.getClass().getName() + ": " + e.getMessage()); + } + + // remove shutdown hook after execution + runnable = new Runnable() { + + @Override + public void run() { + try { + Timer.this.run(); + } finally { + cancel(); + } + } + }; + } else { + try { + // remove existing shutdown hook, if any + removeShutdownHook(); + } catch (Exception e) { + // may fail if running with restricted permissions + Logger.getLogger(getClass().getName()).log(Level.WARNING, e.getClass().getName() + ": " + e.getMessage()); + } + } + + scheduledFuture = executor.schedule(runnable, delay, unit); + } + + public synchronized void cancel() { + removeShutdownHook(); + if (executor != null) { + executor.shutdownNow(); + } + + scheduledFuture = null; + executor = null; + } + + private synchronized void addShutdownHook() { + if (shutdownHook == null) { + shutdownHook = new Thread(this); + Runtime.getRuntime().addShutdownHook(shutdownHook); + } + } + + private synchronized void removeShutdownHook() { + if (shutdownHook != null) { + try { + if (shutdownHook != Thread.currentThread()) { + // can't remove shutdown hooks anymore, once runtime is shutting down, + // so don't remove the shutdown hook, if we are running on the shutdown hook + Runtime.getRuntime().removeShutdownHook(shutdownHook); + } + } finally { + shutdownHook = null; + } + } + } + +} diff --git a/source/net/sourceforge/filebot/util/TreeIterator.java b/source/net/sourceforge/filebot/util/TreeIterator.java new file mode 100644 index 00000000..a9b1e34b --- /dev/null +++ b/source/net/sourceforge/filebot/util/TreeIterator.java @@ -0,0 +1,63 @@ + +package net.sourceforge.filebot.util; + + +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedList; + + +public abstract class TreeIterator implements Iterator { + + private final LinkedList> recursionStack = new LinkedList>(); + + + public TreeIterator(T... root) { + recursionStack.push(Arrays.asList(root).iterator()); + } + + + protected abstract Iterator children(T node); + + + @Override + public boolean hasNext() { + return currentIterator().hasNext(); + } + + + @Override + public T next() { + T node = currentIterator().next(); + + Iterator children = children(node); + if (children != null && children.hasNext()) { + // step into next recursion level + recursionStack.push(children); + } + + return node; + } + + + private Iterator currentIterator() { + Iterator iterator = recursionStack.peek(); + + if (iterator.hasNext() || recursionStack.size() <= 1) + return iterator; + + // step back one recursion level + recursionStack.pop(); + + return currentIterator(); + } + + + @Override + public void remove() { + // can't just use remove() on current iterator, because + // we may have stepped into the next recursion level + throw new UnsupportedOperationException(); + } + +} diff --git a/source/net/sourceforge/filebot/util/XPathUtilities.java b/source/net/sourceforge/filebot/util/XPathUtilities.java new file mode 100644 index 00000000..77335586 --- /dev/null +++ b/source/net/sourceforge/filebot/util/XPathUtilities.java @@ -0,0 +1,160 @@ + +package net.sourceforge.filebot.util; + + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + + +public final class XPathUtilities { + + public static Node selectNode(String xpath, Object node) { + try { + return (Node) getXPath(xpath).evaluate(node, XPathConstants.NODE); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + + public static List selectNodes(String xpath, Object node) { + try { + return new NodeListDecorator((NodeList) getXPath(xpath).evaluate(node, XPathConstants.NODESET)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + + public static String selectString(String xpath, Object node) { + try { + return ((String) getXPath(xpath).evaluate(node, XPathConstants.STRING)).trim(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + + /** + * @param nodeName search for nodes with this name + * @param parentNode search in the child nodes of this nodes + * @return text content of the child node or null if no child with the given name was found + */ + public static Node getChild(String nodeName, Node parentNode) { + for (Node child : new NodeListDecorator(parentNode.getChildNodes())) { + if (nodeName.equals(child.getNodeName())) + return child; + } + + return null; + } + + + public static List getChildren(String nodeName, Node parentNode) { + List children = new ArrayList(); + + for (Node child : new NodeListDecorator(parentNode.getChildNodes())) { + if (nodeName.equals(child.getNodeName())) + children.add(child); + } + + return children; + } + + + public static String getAttribute(String attribute, Node node) { + Node attributeNode = node.getAttributes().getNamedItem(attribute); + + if (attributeNode != null) + return attributeNode.getNodeValue().trim(); + + return null; + } + + + /** + * Get text content of the first child node matching the given node name. Use this method + * instead of {@link #selectString(String, Object)} whenever xpath support is not required, + * because it is much faster, especially for large documents. + * + * @param childName search for nodes with this name + * @param parentNode search in the child nodes of this nodes + * @return text content of the child node or null if no child with the given name was found + */ + public static String getTextContent(String childName, Node parentNode) { + Node child = getChild(childName, parentNode); + + if (child == null) { + return null; + } + + return getTextContent(child); + } + + + public static String getTextContent(Node node) { + StringBuilder sb = new StringBuilder(); + + for (Node textNode : getChildren("#text", node)) { + sb.append(textNode.getNodeValue()); + } + + return sb.toString().trim(); + } + + + public static Integer getIntegerContent(String childName, Node parentNode) { + try { + return new Integer(getTextContent(childName, parentNode)); + } catch (NumberFormatException e) { + return null; + } + } + + + private static XPathExpression getXPath(String xpath) throws XPathExpressionException { + return XPathFactory.newInstance().newXPath().compile(xpath); + } + + + /** + * Dummy constructor to prevent instantiation. + */ + private XPathUtilities() { + throw new UnsupportedOperationException(); + } + + + protected static class NodeListDecorator extends AbstractList { + + private final NodeList nodes; + + + public NodeListDecorator(NodeList nodes) { + this.nodes = nodes; + } + + + @Override + public Node get(int index) { + return nodes.item(index); + } + + + @Override + public int size() { + return nodes.getLength(); + } + + } + +} diff --git a/source/net/sourceforge/filebot/util/prefs/FilePreferences.java b/source/net/sourceforge/filebot/util/prefs/FilePreferences.java new file mode 100644 index 00000000..cd9db917 --- /dev/null +++ b/source/net/sourceforge/filebot/util/prefs/FilePreferences.java @@ -0,0 +1,216 @@ +// https://github.com/sonatype/nexus/blob/2f0e154ec565969b4fd8698883ab76a461210f4f/nexus/nexus-test-harness/nexus-it-helper-plugin/src/main/java/org/sonatype/nexus/rt/prefs/FilePreferences.java + +package net.sourceforge.filebot.util.prefs; + + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.TreeMap; +import java.util.prefs.AbstractPreferences; +import java.util.prefs.BackingStoreException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * Preferences implementation that stores to a user-defined file. See FilePreferencesFactory. Modified by cstamas, + * switched to SLF4J logging, and exposed preferences file property. + * + * Modified to use '/' as path separator and not '.' because it breaks when keys containing '.' are used. + * + * @author David Croft (www.davidc.net) + * @version $Id: FilePreferences.java 283 2009-06-18 17:06:58Z david $ + */ +public class FilePreferences extends AbstractPreferences { + + private static final Logger log = LoggerFactory.getLogger(FilePreferences.class.getName()); + + private Map root; + + private Map children; + + private boolean isRemoved = false; + + + public FilePreferences(AbstractPreferences parent, String name) { + super(parent, name); + + log.debug("Instantiating node {}", name); + + root = new TreeMap(); + children = new TreeMap(); + + try { + sync(); + } catch (BackingStoreException e) { + log.error("Unable to sync on creation of node " + name, e); + } + } + + + @Override + protected void putSpi(String key, String value) { + root.put(key, value); + try { + flush(); + } catch (BackingStoreException e) { + log.error("Unable to flush after putting " + key, e); + } + } + + + @Override + protected String getSpi(String key) { + return root.get(key); + } + + + @Override + protected void removeSpi(String key) { + root.remove(key); + try { + flush(); + } catch (BackingStoreException e) { + log.error("Unable to flush after removing " + key, e); + } + } + + + @Override + protected void removeNodeSpi() throws BackingStoreException { + isRemoved = true; + flush(); + } + + + @Override + protected String[] keysSpi() throws BackingStoreException { + return root.keySet().toArray(new String[root.keySet().size()]); + } + + + @Override + protected String[] childrenNamesSpi() throws BackingStoreException { + return children.keySet().toArray(new String[children.keySet().size()]); + } + + + @Override + protected FilePreferences childSpi(String name) { + FilePreferences child = children.get(name); + if (child == null || child.isRemoved()) { + child = new FilePreferences(this, name); + children.put(name, child); + } + return child; + } + + + @Override + protected void syncSpi() throws BackingStoreException { + if (isRemoved()) { + return; + } + + final File file = FilePreferencesFactory.getPreferencesFile(); + + if (!file.exists()) { + return; + } + + synchronized (file) { + Properties p = new Properties(); + try { + p.load(new FileInputStream(file)); + + StringBuilder sb = new StringBuilder(); + getPath(sb); + String path = sb.toString(); + + final Enumeration pnen = p.propertyNames(); + while (pnen.hasMoreElements()) { + String propKey = (String) pnen.nextElement(); + if (propKey.startsWith(path)) { + String subKey = propKey.substring(path.length()); + // Only load immediate descendants + if (subKey.indexOf('/') == -1) { + root.put(subKey, p.getProperty(propKey)); + } + } + } + } catch (IOException e) { + throw new BackingStoreException(e); + } + } + } + + + private void getPath(StringBuilder sb) { + final FilePreferences parent = (FilePreferences) parent(); + if (parent == null) { + return; + } + + parent.getPath(sb); + sb.append(name()).append('/'); + } + + + @Override + protected void flushSpi() throws BackingStoreException { + final File file = FilePreferencesFactory.getPreferencesFile(); + + synchronized (file) { + Properties p = new Properties(); + try { + + StringBuilder sb = new StringBuilder(); + getPath(sb); + String path = sb.toString(); + + if (file.exists()) { + p.load(new FileInputStream(file)); + + List toRemove = new ArrayList(); + + // Make a list of all direct children of this node to be removed + final Enumeration pnen = p.propertyNames(); + while (pnen.hasMoreElements()) { + String propKey = (String) pnen.nextElement(); + if (propKey.startsWith(path)) { + String subKey = propKey.substring(path.length()); + // Only do immediate descendants + if (subKey.indexOf('/') == -1) { + toRemove.add(propKey); + } + } + } + + // Remove them now that the enumeration is done with + for (String propKey : toRemove) { + p.remove(propKey); + } + } + + // If this node hasn't been removed, add back in any values + if (!isRemoved) { + for (String s : root.keySet()) { + p.setProperty(path + s, root.get(s)); + } + } + + p.store(new FileOutputStream(file), "FilePreferences"); + } catch (IOException e) { + throw new BackingStoreException(e); + } + } + } +} diff --git a/source/net/sourceforge/filebot/util/prefs/FilePreferencesFactory.java b/source/net/sourceforge/filebot/util/prefs/FilePreferencesFactory.java new file mode 100644 index 00000000..5ceb65a7 --- /dev/null +++ b/source/net/sourceforge/filebot/util/prefs/FilePreferencesFactory.java @@ -0,0 +1,63 @@ +// https://github.com/sonatype/nexus/blob/2f0e154ec565969b4fd8698883ab76a461210f4f/nexus/nexus-test-harness/nexus-it-helper-plugin/src/main/java/org/sonatype/nexus/rt/prefs/FilePreferencesFactory.java + +package net.sourceforge.filebot.util.prefs; + + +import java.io.File; +import java.util.prefs.Preferences; +import java.util.prefs.PreferencesFactory; + + +/** + * PreferencesFactory implementation that stores the preferences in a user-defined file. To use it, set the system + * property java.util.prefs.PreferencesFactory to net.sourceforge.filebot.util.pref.FilePreferencesFactory + *

+ * The file defaults to [user.home]/.fileprefs, but may be overridden with the system property + * net.sourceforge.filebot.util.pref.FilePreferencesFactory.file. Modified by cstamas, switched to SLF4J logging, and + * exposed preferences file property. + * + * @author David Croft (www.davidc.net) + * @version $Id: FilePreferencesFactory.java 282 2009-06-18 17:05:18Z david $ + */ +public class FilePreferencesFactory implements PreferencesFactory { + + Preferences rootPreferences; + + public static final String SYSTEM_PROPERTY_FILE = "net.sourceforge.filebot.util.prefs.file"; + + + public Preferences systemRoot() { + return userRoot(); + } + + + public Preferences userRoot() { + if (rootPreferences == null) { + rootPreferences = new FilePreferences(null, ""); + } + + return rootPreferences; + } + + private static File preferencesFile; + + + public static File getPreferencesFile() { + if (preferencesFile == null) { + String prefsFile = System.getProperty(SYSTEM_PROPERTY_FILE); + + if (prefsFile == null || prefsFile.length() == 0) { + prefsFile = System.getProperty("user.home") + File.separator + ".fileprefs"; + } + + preferencesFile = new File(prefsFile).getAbsoluteFile(); + } + + return preferencesFile; + } + + + public static void setPreferencesFile(File file) { + preferencesFile = file; + } +} diff --git a/source/net/sourceforge/filebot/util/ui/AbstractBean.java b/source/net/sourceforge/filebot/util/ui/AbstractBean.java new file mode 100644 index 00000000..98a04571 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/AbstractBean.java @@ -0,0 +1,47 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +import javax.swing.event.SwingPropertyChangeSupport; + + +public abstract class AbstractBean { + + private final PropertyChangeSupport pcs; + + + public AbstractBean() { + // always notify on EDT + pcs = new SwingPropertyChangeSupport(this, true); + } + + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + + protected void firePropertyChange(PropertyChangeEvent e) { + pcs.firePropertyChange(e); + } + + + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + + public PropertyChangeListener[] getPropertyChangeListeners() { + return pcs.getPropertyChangeListeners(); + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/AbstractFancyListCellRenderer.java b/source/net/sourceforge/filebot/util/ui/AbstractFancyListCellRenderer.java new file mode 100644 index 00000000..8f82ce32 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/AbstractFancyListCellRenderer.java @@ -0,0 +1,312 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.awt.Color; +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.geom.Rectangle2D; + +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; +import javax.swing.border.Border; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.LineBorder; + + +public abstract class AbstractFancyListCellRenderer extends JPanel implements ListCellRenderer { + + private Color gradientBeginColor; + private Color gradientEndColor; + + private Color highlightColor; + + private boolean borderPainted = false; + private boolean gradientPainted = false; + + private GradientStyle gradientStyle = GradientStyle.TOP_TO_BOTTOM; + private boolean highlightingEnabled = true; + + private final Insets margin; + + private static final Insets DEFAULT_PADDING = new Insets(7, 7, 7, 7); + private static final Insets DEFAULT_MARGIN = new Insets(1, 1, 0, 1); + + + public AbstractFancyListCellRenderer() { + this(DEFAULT_PADDING, DEFAULT_MARGIN, null); + } + + + public AbstractFancyListCellRenderer(Insets padding) { + this(padding, DEFAULT_MARGIN, null); + } + + + public AbstractFancyListCellRenderer(Insets padding, Insets margin) { + this(padding, margin, null); + } + + + public AbstractFancyListCellRenderer(Insets padding, Insets margin, Color borderColor) { + this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + + Border border = null; + + if (padding != null) + border = new EmptyBorder(padding); + + if (borderColor != null) + border = new CompoundBorder(new LineBorder(borderColor, 1), border); + + if (margin != null) { + this.margin = margin; + border = new CompoundBorder(new EmptyBorder(margin), border); + } else { + this.margin = new Insets(0, 0, 0, 0); + } + + setBorder(border); + setOpaque(false); + } + + + @Override + protected void paintBorder(Graphics g) { + if (borderPainted) { + super.paintBorder(g); + } + } + + + @Override + protected void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + Rectangle2D shape = new Rectangle2D.Double(margin.left, margin.top, getWidth() - (margin.left + margin.right), getHeight() - (margin.top + margin.bottom)); + + if (isOpaque()) { + g2d.setPaint(getBackground()); + g2d.fill(shape); + } + + if (highlightingEnabled && (highlightColor != null)) { + g2d.setPaint(highlightColor); + g2d.fill(shape); + } + + if (gradientPainted) { + g2d.setPaint(gradientStyle.getGradientPaint(shape, gradientBeginColor, gradientEndColor)); + g2d.fill(shape); + } + + super.paintComponent(g); + } + + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + configureListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + validate(); + + return this; + } + + + protected void configureListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + setGradientPainted(isSelected); + setBorderPainted(isSelected); + + Color sc = list.getSelectionBackground(); + + if (isSelected) { + setGradientColors(sc.brighter(), sc); + } + + if (highlightingEnabled && ((index % 2) == 0)) { + setHighlightColor(new Color(sc.getRed(), sc.getGreen(), sc.getBlue(), 28)); + } else { + setHighlightColor(null); + } + + if (isSelected) { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } else { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + } + } + + + public void setGradientColors(Color gradientBeginColor, Color gradientEndColor) { + this.gradientBeginColor = gradientBeginColor; + this.gradientEndColor = gradientEndColor; + } + + + public Color getGradientBeginColor() { + return gradientBeginColor; + } + + + public Color getGradientEndColor() { + return gradientEndColor; + } + + + public void setHighlightColor(Color highlightColor) { + this.highlightColor = highlightColor; + } + + + public void setGradientStyle(GradientStyle gradientStyle) { + this.gradientStyle = gradientStyle; + } + + + public void setHighlightingEnabled(boolean highlightingEnabled) { + this.highlightingEnabled = highlightingEnabled; + } + + + public void setBorderPainted(boolean borderPainted) { + this.borderPainted = borderPainted; + } + + + public void setGradientPainted(boolean gradientPainted) { + this.gradientPainted = gradientPainted; + } + + + public Color getHighlightColor() { + return highlightColor; + } + + + public boolean isBorderPainted() { + return borderPainted; + } + + + public GradientStyle getGradientStyle() { + return gradientStyle; + } + + + public boolean isHighlightingEnabled() { + return highlightingEnabled; + } + + + @Override + public void validate() { + // validate children, yet avoid flickering of the mouse cursor + synchronized (getTreeLock()) { + validateTree(); + } + } + + + /** + * Overridden for performance reasons. + */ + @Override + public void repaint() { + } + + + /** + * Overridden for performance reasons. + */ + @Override + public void repaint(long tm, int x, int y, int width, int height) { + } + + + /** + * Overridden for performance reasons. + */ + @Override + public void repaint(Rectangle r) { + } + + + /** + * Overridden for performance reasons. + */ + @Override + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + } + + + /** + * Overridden for performance reasons. + */ + @Override + public void firePropertyChange(String propertyName, byte oldValue, byte newValue) { + } + + + /** + * Overridden for performance reasons. + */ + @Override + public void firePropertyChange(String propertyName, char oldValue, char newValue) { + } + + + /** + * Overridden for performance reasons. + */ + @Override + public void firePropertyChange(String propertyName, short oldValue, short newValue) { + } + + + /** + * Overridden for performance reasons. + */ + @Override + public void firePropertyChange(String propertyName, int oldValue, int newValue) { + } + + + /** + * Overridden for performance reasons. + */ + @Override + public void firePropertyChange(String propertyName, long oldValue, long newValue) { + } + + + /** + * Overridden for performance reasons. + */ + @Override + public void firePropertyChange(String propertyName, float oldValue, float newValue) { + } + + + /** + * Overridden for performance reasons. + */ + @Override + public void firePropertyChange(String propertyName, double oldValue, double newValue) { + } + + + /** + * Overridden for performance reasons. + */ + @Override + public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) { + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/ActionPopup.java b/source/net/sourceforge/filebot/util/ui/ActionPopup.java new file mode 100644 index 00000000..2e73df40 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/ActionPopup.java @@ -0,0 +1,109 @@ +package net.sourceforge.filebot.util.ui; + +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JSeparator; + +import net.miginfocom.swing.MigLayout; + +public class ActionPopup extends JPopupMenu { + + protected final JLabel headerLabel = new JLabel(); + protected final JLabel descriptionLabel = new JLabel(); + protected final JLabel statusLabel = new JLabel(); + + protected final JPanel actionPanel = new JPanel(new MigLayout("nogrid, insets 0, fill")); + + public ActionPopup(String label, Icon icon) { + headerLabel.setText(label); + headerLabel.setIcon(icon); + headerLabel.setIconTextGap(5); + + actionPanel.setOpaque(false); + + statusLabel.setFont(statusLabel.getFont().deriveFont(10f)); + statusLabel.setForeground(Color.GRAY); + + setLayout(new MigLayout("nogrid, fill, insets 0")); + + add(headerLabel, "gapx 5px 5px, gapy 3px 1px, wrap 3px"); + add(new JSeparator(), "growx, wrap 1px"); + add(actionPanel, "growx, wrap 0px"); + add(new JSeparator(), "growx, wrap 0px"); + add(statusLabel, "growx, h 11px!, gapx 3px, wrap 1px"); + + // make it look better (e.g. window shadows) by forcing heavy-weight windows + setLightWeightPopupEnabled(false); + } + + public void addDescription(JComponent component) { + actionPanel.add(component, "gapx 4px, wrap 3px"); + } + + public void addAction(JComponent component) { + actionPanel.add(component, "gapx 12px 12px, growx, wrap"); + } + + @Override + public void addSeparator() { + actionPanel.add(new JSeparator(), "growx, wrap 1px"); + } + + @Override + public JMenuItem add(Action a) { + LinkButton link = new LinkButton(a); + + // underline text + link.setText(String.format("%s", link.getText())); + + // use rollover color + link.setRolloverEnabled(false); + link.setColor(link.getRolloverColor()); + + // close popup when action is triggered + link.addActionListener(closeListener); + + addAction(link); + return null; + } + + public void clear() { + actionPanel.removeAll(); + } + + @Override + public void setLabel(String label) { + headerLabel.setText(label); + } + + @Override + public String getLabel() { + return headerLabel.getText(); + } + + public void setStatus(String string) { + statusLabel.setText(string); + } + + public String getStatus() { + return statusLabel.getText(); + } + + private final ActionListener closeListener = new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + setVisible(false); + } + }; + +} diff --git a/source/net/sourceforge/filebot/util/ui/ColorTintImageFilter.java b/source/net/sourceforge/filebot/util/ui/ColorTintImageFilter.java new file mode 100644 index 00000000..55fc2e9a --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/ColorTintImageFilter.java @@ -0,0 +1,34 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.awt.Color; +import java.awt.image.RGBImageFilter; + + +public class ColorTintImageFilter extends RGBImageFilter { + + private Color color; + private float intensity; + + + public ColorTintImageFilter(Color color, float intensity) { + this.color = color; + this.intensity = intensity; + + canFilterIndexColorModel = true; + } + + + @Override + public int filterRGB(int x, int y, int rgb) { + Color c = new Color(rgb, true); + + int red = (int) ((c.getRed() * (1 - intensity)) + color.getRed() * intensity); + int green = (int) ((c.getGreen() * (1 - intensity)) + color.getGreen() * intensity); + int blue = (int) ((c.getBlue() * (1 - intensity)) + color.getBlue() * intensity); + + return new Color(red, green, blue, c.getAlpha()).getRGB(); + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/DashedSeparator.java b/source/net/sourceforge/filebot/util/ui/DashedSeparator.java new file mode 100644 index 00000000..026aa566 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/DashedSeparator.java @@ -0,0 +1,64 @@ + +package net.sourceforge.filebot.util.ui; + + +import static java.awt.BasicStroke.*; +import static java.awt.RenderingHints.*; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; + +import javax.swing.border.Border; + + +public class DashedSeparator implements Border { + + private final int height; + private final int dash; + + private final Color foreground; + private final Color background; + + + public DashedSeparator(int height, int dash, Color foreground, Color background) { + this.height = height; + this.dash = dash; + this.foreground = foreground; + this.background = background; + } + + + @Override + public Insets getBorderInsets(Component c) { + return new Insets(0, 0, height, 0); + } + + + @Override + public boolean isBorderOpaque() { + return true; + } + + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + Graphics2D g2d = (Graphics2D) g.create(x, h - this.height, w, h); + + // fill background + g2d.setPaint(background); + g2d.fillRect(0, 0, w, h); + + // draw dashed line + g2d.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON); + g2d.setColor(foreground); + g2d.setStroke(new BasicStroke(1, CAP_ROUND, JOIN_ROUND, 1, new float[] { dash }, 0)); + + g2d.drawLine(dash, this.height / 2, w - dash, this.height / 2); + + g2d.dispose(); + } +} diff --git a/source/net/sourceforge/filebot/util/ui/DefaultFancyListCellRenderer.java b/source/net/sourceforge/filebot/util/ui/DefaultFancyListCellRenderer.java new file mode 100644 index 00000000..74a82f48 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/DefaultFancyListCellRenderer.java @@ -0,0 +1,80 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.awt.Color; +import java.awt.Insets; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.Icon; +import javax.swing.JLabel; +import javax.swing.JList; + + +public class DefaultFancyListCellRenderer extends AbstractFancyListCellRenderer { + + private final JLabel label = new DefaultListCellRenderer(); + + + public DefaultFancyListCellRenderer() { + add(label); + } + + + public DefaultFancyListCellRenderer(int padding) { + super(new Insets(padding, padding, padding, padding)); + add(label); + } + + + public DefaultFancyListCellRenderer(Insets padding) { + super(padding); + add(label); + } + + + protected DefaultFancyListCellRenderer(int padding, int margin, Color selectedBorderColor) { + super(new Insets(padding, padding, padding, padding), new Insets(margin, margin, margin, margin), selectedBorderColor); + add(label); + } + + + @Override + protected void configureListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + super.configureListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + label.setOpaque(false); + setText(String.valueOf(value)); + } + + + public void setIcon(Icon icon) { + label.setIcon(icon); + } + + + public void setText(String text) { + label.setText(text); + } + + + public void setHorizontalTextPosition(int textPosition) { + label.setHorizontalTextPosition(textPosition); + } + + + public void setVerticalTextPosition(int textPosition) { + label.setVerticalTextPosition(textPosition); + } + + + @Override + public void setForeground(Color fg) { + super.setForeground(fg); + + // label is null while in super constructor + if (label != null) { + label.setForeground(fg); + } + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/EmptySelectionModel.java b/source/net/sourceforge/filebot/util/ui/EmptySelectionModel.java new file mode 100644 index 00000000..64481656 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/EmptySelectionModel.java @@ -0,0 +1,118 @@ + +package net.sourceforge.filebot.util.ui; + + +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionListener; + + +public class EmptySelectionModel implements ListSelectionModel { + + @Override + public void addListSelectionListener(ListSelectionListener x) { + } + + + @Override + public void addSelectionInterval(int from, int to) { + } + + + @Override + public void clearSelection() { + } + + + @Override + public int getAnchorSelectionIndex() { + return -1; + } + + + @Override + public int getLeadSelectionIndex() { + return -1; + } + + + @Override + public int getMaxSelectionIndex() { + return -1; + } + + + @Override + public int getMinSelectionIndex() { + return -1; + } + + + @Override + public int getSelectionMode() { + return -1; + } + + + @Override + public boolean getValueIsAdjusting() { + return false; + } + + + @Override + public void insertIndexInterval(int index, int length, boolean before) { + } + + + @Override + public boolean isSelectedIndex(int index) { + return false; + } + + + @Override + public boolean isSelectionEmpty() { + return true; + } + + + @Override + public void removeIndexInterval(int from, int to) { + } + + + @Override + public void removeListSelectionListener(ListSelectionListener listener) { + } + + + @Override + public void removeSelectionInterval(int from, int to) { + } + + + @Override + public void setAnchorSelectionIndex(int index) { + } + + + @Override + public void setLeadSelectionIndex(int index) { + } + + + @Override + public void setSelectionInterval(int from, int to) { + } + + + @Override + public void setSelectionMode(int selectionMode) { + } + + + @Override + public void setValueIsAdjusting(boolean valueIsAdjusting) { + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/FancyTreeCellRenderer.java b/source/net/sourceforge/filebot/util/ui/FancyTreeCellRenderer.java new file mode 100644 index 00000000..91f0033f --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/FancyTreeCellRenderer.java @@ -0,0 +1,130 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.RoundRectangle2D; + +import javax.swing.Icon; +import javax.swing.JTree; +import javax.swing.tree.DefaultTreeCellRenderer; + + +public class FancyTreeCellRenderer extends DefaultTreeCellRenderer { + + private Color gradientBeginColor; + private Color gradientEndColor; + private GradientStyle gradientStyle; + private boolean paintGradient; + + private Color backgroundSelectionColor; + + + public FancyTreeCellRenderer() { + this(GradientStyle.TOP_TO_BOTTOM); + } + + + public FancyTreeCellRenderer(GradientStyle gradientStyle) { + this.gradientStyle = gradientStyle; + + backgroundSelectionColor = getBackgroundSelectionColor(); + + // disable default selection background + setBackgroundSelectionColor(null); + } + + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, false); + + setIconTextGap(5); + + if (selected) { + setPaintGradient(true); + setGradientBeginColor(backgroundSelectionColor.brighter()); + setGradientEndColor(backgroundSelectionColor); + } else { + setPaintGradient(false); + } + + return this; + } + + + @Override + protected void paintComponent(Graphics g) { + if (isPaintGradient()) { + Graphics2D g2d = (Graphics2D) g; + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + int imageOffset = getLabelStart() - 2; + + int arch = 16; + RoundRectangle2D shape = new RoundRectangle2D.Double(imageOffset, 1, getWidth() - imageOffset, getHeight() - 2, arch, arch); + + g2d.setPaint(gradientStyle.getGradientPaint(shape, gradientBeginColor, gradientEndColor)); + g2d.fill(shape); + } + + super.paintComponent(g); + } + + + protected int getLabelStart() { + Icon icon = getIcon(); + + if ((icon != null) && (getText() != null)) { + return icon.getIconWidth() + Math.max(0, getIconTextGap() - 1); + } + + return 0; + } + + + public Color getGradientBeginColor() { + return gradientBeginColor; + } + + + public void setGradientBeginColor(Color gradientBeginColor) { + this.gradientBeginColor = gradientBeginColor; + } + + + public boolean isPaintGradient() { + return paintGradient; + } + + + public void setPaintGradient(boolean gradientEnabled) { + this.paintGradient = gradientEnabled; + } + + + public Color getGradientEndColor() { + return gradientEndColor; + } + + + public void setGradientEndColor(Color gradientEndColor) { + this.gradientEndColor = gradientEndColor; + } + + + public GradientStyle getGradientStyle() { + return gradientStyle; + } + + + public void setGradientStyle(GradientStyle gradientStyle) { + this.gradientStyle = gradientStyle; + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/GradientStyle.java b/source/net/sourceforge/filebot/util/ui/GradientStyle.java new file mode 100644 index 00000000..f11d9f86 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/GradientStyle.java @@ -0,0 +1,76 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.awt.Color; +import java.awt.LinearGradientPaint; +import java.awt.MultipleGradientPaint.CycleMethod; +import java.awt.geom.Point2D; +import java.awt.geom.RectangularShape; + + +public enum GradientStyle { + TOP_TO_BOTTOM, + BOTTOM_TO_TOP, + LEFT_TO_RIGHT, + RIGHT_TO_LEFT, + TOP_LEFT_TO_BOTTOM_RIGHT, + BOTTOM_RIGHT_TO_TOP_LEFT, + TOP_RIGHT_TO_BOTTOM_LEFT, + BOTTOM_LEFT_TO_TOP_RIGHT; + + public LinearGradientPaint getGradientPaint(RectangularShape shape, Color gradientBeginColor, Color gradientEndColor) { + Point2D start = null; + Point2D end = null; + + switch (this) { + case BOTTOM_TO_TOP: + start = new Point2D.Double(shape.getCenterX(), shape.getMaxY()); + end = new Point2D.Double(shape.getCenterX(), shape.getMinY()); + break; + + case TOP_TO_BOTTOM: + end = new Point2D.Double(shape.getCenterX(), shape.getMaxY()); + start = new Point2D.Double(shape.getCenterX(), shape.getMinY()); + break; + + case LEFT_TO_RIGHT: + start = new Point2D.Double(shape.getMinX(), shape.getCenterY()); + end = new Point2D.Double(shape.getMaxX(), shape.getCenterY()); + break; + + case RIGHT_TO_LEFT: + end = new Point2D.Double(shape.getMinX(), shape.getCenterY()); + start = new Point2D.Double(shape.getMaxX(), shape.getCenterY()); + break; + + case TOP_LEFT_TO_BOTTOM_RIGHT: + start = new Point2D.Double(shape.getMinX(), shape.getMinY()); + end = new Point2D.Double(shape.getMaxX(), shape.getMaxY()); + break; + + case BOTTOM_RIGHT_TO_TOP_LEFT: + end = new Point2D.Double(shape.getMinX(), shape.getMinY()); + start = new Point2D.Double(shape.getMaxX(), shape.getMaxY()); + break; + + case TOP_RIGHT_TO_BOTTOM_LEFT: + start = new Point2D.Double(shape.getMaxX(), shape.getMinY()); + end = new Point2D.Double(shape.getMinX(), shape.getMaxY()); + break; + + case BOTTOM_LEFT_TO_TOP_RIGHT: + end = new Point2D.Double(shape.getMaxX(), shape.getMinY()); + start = new Point2D.Double(shape.getMinX(), shape.getMaxY()); + break; + + default: + return null; + } + + Color[] colors = { gradientBeginColor, gradientEndColor }; + float[] fractions = { 0.0f, 1.0f }; + return new LinearGradientPaint(start, end, fractions, colors, CycleMethod.NO_CYCLE); + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/LabelProvider.java b/source/net/sourceforge/filebot/util/ui/LabelProvider.java new file mode 100644 index 00000000..03e40639 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/LabelProvider.java @@ -0,0 +1,15 @@ + +package net.sourceforge.filebot.util.ui; + + +import javax.swing.Icon; + + +public interface LabelProvider { + + public String getText(T value); + + + public Icon getIcon(T value); + +} diff --git a/source/net/sourceforge/filebot/util/ui/LazyDocumentListener.java b/source/net/sourceforge/filebot/util/ui/LazyDocumentListener.java new file mode 100644 index 00000000..e877e207 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/LazyDocumentListener.java @@ -0,0 +1,76 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.Timer; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + + +public abstract class LazyDocumentListener implements DocumentListener { + + private DocumentEvent lastEvent; + + private Timer timer; + + + public LazyDocumentListener() { + this(200); + } + + + public LazyDocumentListener(int delay) { + if (delay >= 0) { + timer = new Timer(delay, new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + update(lastEvent); + + // we don't need it anymore + lastEvent = null; + } + }); + + timer.setRepeats(false); + } + } + + + public void defer(DocumentEvent e) { + lastEvent = e; + + if (timer != null) { + // defer update + timer.restart(); + } else { + // update immediately + update(lastEvent); + } + } + + + @Override + public void changedUpdate(DocumentEvent e) { + defer(e); + } + + + @Override + public void insertUpdate(DocumentEvent e) { + defer(e); + } + + + @Override + public void removeUpdate(DocumentEvent e) { + defer(e); + } + + + public abstract void update(DocumentEvent e); + +} diff --git a/source/net/sourceforge/filebot/util/ui/LinkButton.java b/source/net/sourceforge/filebot/util/ui/LinkButton.java new file mode 100644 index 00000000..a860243c --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/LinkButton.java @@ -0,0 +1,124 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Desktop; +import java.awt.event.ActionEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.net.URI; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JButton; + + +public class LinkButton extends JButton { + + private Color color = getForeground(); + private Color rolloverColor = new Color(0x3399FF); + + + public LinkButton(String text, Icon icon, URI uri) { + this(new OpenUriAction(text, icon, uri)); + } + + + public LinkButton(Action action) { + setAction(action); + + setFocusPainted(false); + setOpaque(false); + setContentAreaFilled(false); + setBorder(null); + + setHorizontalAlignment(LEFT); + setIconTextGap(6); + setRolloverEnabled(true); + + setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + } + + + @Override + public void setRolloverEnabled(boolean enabled) { + super.setRolloverEnabled(enabled); + + // always remove listener if there is one + removeMouseListener(rolloverListener); + + if (enabled) { + // add listener again, if enabled + addMouseListener(rolloverListener); + } + } + + + public Color getColor() { + return color; + } + + + public void setColor(Color color) { + this.color = color; + this.setForeground(color); + } + + + public Color getRolloverColor() { + return rolloverColor; + } + + + public void setRolloverColor(Color rolloverColor) { + this.rolloverColor = rolloverColor; + } + + protected final MouseListener rolloverListener = new MouseAdapter() { + + @Override + public void mouseEntered(MouseEvent e) { + setForeground(rolloverColor); + } + + + @Override + public void mouseExited(MouseEvent e) { + setForeground(color); + } + }; + + + protected static class OpenUriAction extends AbstractAction { + + public static final String URI = "uri"; + + + public OpenUriAction(String text, Icon icon, URI uri) { + super(text, icon); + putValue(URI, uri); + } + + + @Override + public void actionPerformed(ActionEvent evt) { + try { + URI uri = (URI) getValue(URI); + + if (uri != null) { + Desktop.getDesktop().browse(uri); + } + } catch (Exception e) { + // should not happen + Logger.getLogger(getClass().getName()).log(Level.SEVERE, e.toString(), e); + } + } + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/ListView.java b/source/net/sourceforge/filebot/util/ui/ListView.java new file mode 100644 index 00000000..bb349ebc --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/ListView.java @@ -0,0 +1,204 @@ + +package net.sourceforge.filebot.util.ui; + + +import static java.lang.Math.*; + +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; +import java.awt.geom.Rectangle2D; +import java.awt.image.FilteredImageSource; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.DropMode; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JList; +import javax.swing.ListModel; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import javax.swing.event.MouseInputAdapter; + + +public class ListView extends JList { + + protected final BlockSelectionHandler blockSelectionHandler = new BlockSelectionHandler(); + + + public ListView(ListModel dataModel) { + super(dataModel); + setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + + // better selection behaviour + putClientProperty("List.isFileList", Boolean.TRUE); + setDropMode(DropMode.ON); + + setLayoutOrientation(JList.VERTICAL_WRAP); + setVisibleRowCount(-1); + setCellRenderer(new ListViewRenderer()); + + addMouseListener(blockSelectionHandler); + addMouseMotionListener(blockSelectionHandler); + } + + + public void addSelectionInterval(Rectangle selection) { + Point p1 = selection.getLocation(); + Point p2 = new Point(p1.x + selection.width, p1.y + selection.height); + + int startIndex = locationToIndex(p1); + int endIndex = locationToIndex(p2); + + for (int i = startIndex; i <= endIndex; i++) { + Rectangle cell = getCellBounds(i, i); + + if (cell != null && selection.intersects(cell)) { + addSelectionInterval(i, i); + } + } + } + + + @Override + public void paintComponent(Graphics g) { + super.paintComponent(g); + + Rectangle selection = blockSelectionHandler.getSelection(); + + // paint block selection + if (selection != null) { + paintBlockSelection((Graphics2D) g, selection); + } + } + + + protected void paintBlockSelection(Graphics2D g2d, Rectangle selection) { + g2d.setPaint(TunedUtilities.derive(getSelectionBackground(), 0.3f)); + g2d.fill(selection); + + g2d.setPaint(getSelectionBackground()); + g2d.draw(selection); + } + + + protected String convertValueToText(Object value) { + return value.toString(); + } + + + protected Icon convertValueToIcon(Object value) { + return null; + } + + + protected class ListViewRenderer extends DefaultListCellRenderer { + + public ListViewRenderer() { + setOpaque(false); + } + + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + Icon icon = convertValueToIcon(value); + + if (isSelected && icon != null) { + // apply selection color tint + icon = new ImageIcon(createImage(new FilteredImageSource(TunedUtilities.getImage(icon).getSource(), new ColorTintImageFilter(list.getSelectionBackground(), 0.5f)))); + } + + setText(convertValueToText(value)); + setIcon(icon); + + if (isSelected) { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } else { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + } + + return this; + } + + + @Override + protected void paintComponent(Graphics g) { + // paint selection background for the text area only, not the whole cell + int iconWidth = (getIcon() == null ? 0 : getIcon().getIconHeight()); + int startX = iconWidth + getIconTextGap(); + Rectangle2D text = getFontMetrics(getFont()).getStringBounds(getText(), g); + + g.setColor(getBackground()); + g.fillRect(startX - 2, 1, (int) (text.getWidth() + 6), getHeight() - 1); + + super.paintComponent(g); + } + }; + + + protected class BlockSelectionHandler extends MouseInputAdapter { + + private Rectangle selection; + + private Point origin; + + + public void mousePressed(MouseEvent e) { + if (SwingUtilities.isLeftMouseButton(e) && !isSelectedIndex(locationToIndex(e.getPoint()))) { + origin = e.getPoint(); + } + } + + + @Override + public void mouseDragged(MouseEvent e) { + if (origin == null) + return; + + // begin selection + if (selection == null) + selection = new Rectangle(); + + // keep point within component bounds + Point p2 = e.getPoint(); + p2.x = max(0, min(getWidth() - 1, p2.x)); + p2.y = max(0, min(getHeight() - 1, p2.y)); + + // update selection bounds + selection.setFrameFromDiagonal(origin, p2); + + // auto-scroll + ensureIndexIsVisible(locationToIndex(p2)); + + // update list selection + clearSelection(); + addSelectionInterval(selection); + + // update view + repaint(); + } + + + @Override + public void mouseReleased(MouseEvent e) { + origin = null; + + // end selection + selection = null; + + // update view + repaint(); + } + + + public Rectangle getSelection() { + return selection; + } + }; + +} diff --git a/source/net/sourceforge/filebot/util/ui/LoadingOverlayPane.java b/source/net/sourceforge/filebot/util/ui/LoadingOverlayPane.java new file mode 100644 index 00000000..c548dcdf --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/LoadingOverlayPane.java @@ -0,0 +1,75 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JComponent; + +import net.miginfocom.swing.MigLayout; + + +public class LoadingOverlayPane extends JComponent { + + public static final String LOADING_PROPERTY = "loading"; + + private final JComponent animationComponent; + + private boolean overlayEnabled = false; + + private int millisToOverlay = 400; + + + public LoadingOverlayPane(JComponent component, JComponent propertyChangeSource) { + this(component, propertyChangeSource, null, null); + } + + + public LoadingOverlayPane(JComponent component, JComponent propertyChangeSource, String offsetX, String offsetY) { + setLayout(new MigLayout("insets 0, fill")); + + animationComponent = new ProgressIndicator(); + animationComponent.setVisible(false); + + add(animationComponent, String.format("pos n %s 100%%-%s n", offsetY != null ? offsetY : "8px", offsetX != null ? offsetX : "20px")); + add(component, "grow"); + + if (propertyChangeSource != null) { + propertyChangeSource.addPropertyChangeListener(LOADING_PROPERTY, new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + setOverlayVisible((Boolean) evt.getNewValue()); + } + }); + } + } + + + @Override + public boolean isOptimizedDrawingEnabled() { + return false; + } + + + public void setOverlayVisible(boolean b) { + overlayEnabled = b; + + if (overlayEnabled) { + TunedUtilities.invokeLater(millisToOverlay, new Runnable() { + + @Override + public void run() { + if (overlayEnabled) { + animationComponent.setVisible(true); + } + } + + }); + } else { + animationComponent.setVisible(false); + } + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/NullLabelProvider.java b/source/net/sourceforge/filebot/util/ui/NullLabelProvider.java new file mode 100644 index 00000000..e61ca39c --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/NullLabelProvider.java @@ -0,0 +1,21 @@ + +package net.sourceforge.filebot.util.ui; + + +import javax.swing.Icon; + + +public class NullLabelProvider implements LabelProvider { + + @Override + public Icon getIcon(T value) { + return null; + } + + + @Override + public String getText(T value) { + return value.toString(); + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/ProgressDialog.java b/source/net/sourceforge/filebot/util/ui/ProgressDialog.java new file mode 100644 index 00000000..c4998cc5 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/ProgressDialog.java @@ -0,0 +1,112 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.awt.Window; +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JProgressBar; + +import net.miginfocom.swing.MigLayout; + + +public class ProgressDialog extends JDialog { + + private final JProgressBar progressBar = new JProgressBar(0, 100); + private final JLabel iconLabel = new JLabel(); + private final JLabel headerLabel = new JLabel(); + + private final Cancellable cancellable; + + + public ProgressDialog(Window owner, Cancellable cancellable) { + super(owner, ModalityType.DOCUMENT_MODAL); + + this.cancellable = cancellable; + + // disable window close button + setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); + + headerLabel.setFont(headerLabel.getFont().deriveFont(18f)); + progressBar.setIndeterminate(true); + progressBar.setStringPainted(true); + JPanel c = (JPanel) getContentPane(); + c.setLayout(new MigLayout("insets dialog, nogrid, fill")); + + c.add(iconLabel, "h pref!, w pref!"); + c.add(headerLabel, "gap 3mm, wrap paragraph"); + c.add(progressBar, "hmin 25px, grow, wrap paragraph"); + + c.add(new JButton(cancelAction), "align center"); + + setSize(240, 155); + } + + + public void setIcon(Icon icon) { + iconLabel.setIcon(icon); + } + + + public void setIndeterminate(boolean b) { + progressBar.setIndeterminate(b); + } + + + public void setProgress(int value, int max) { + progressBar.setIndeterminate(false); + progressBar.setMinimum(0); + progressBar.setValue(value); + progressBar.setMaximum(max); + } + + + public void setNote(String text) { + progressBar.setString(text); + } + + + @Override + public void setTitle(String text) { + super.setTitle(text); + headerLabel.setText(text); + } + + + public void setWindowTitle(String text) { + super.setTitle(text); + } + + + public void close() { + setVisible(false); + dispose(); + } + + + protected final Action cancelAction = new AbstractAction("Cancel") { + + @Override + public void actionPerformed(ActionEvent e) { + cancelAction.setEnabled(false); + cancellable.cancel(); + } + }; + + + public static interface Cancellable { + + boolean isCancelled(); + + + boolean cancel(); + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/ProgressIndicator.java b/source/net/sourceforge/filebot/util/ui/ProgressIndicator.java new file mode 100644 index 00000000..9a48ec6b --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/ProgressIndicator.java @@ -0,0 +1,157 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Stroke; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import javax.swing.JComponent; +import javax.swing.Timer; + + +public class ProgressIndicator extends JComponent { + + private float radius = 4.0f; + private int shapeCount = 3; + + private float strokeWidth = 2f; + private Stroke stroke = new BasicStroke(strokeWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND); + + private Color progressShapeColor = Color.orange; + private Color backgroundShapeColor = new Color(0f, 0f, 0f, 0.25f); + + private final Rectangle2D frame = new Rectangle2D.Double(); + private final Ellipse2D circle = new Ellipse2D.Double(); + private final Dimension baseSize = new Dimension(32, 32); + + private double alpha = 0; + private double speed = 24; + + private Timer updateTimer; + + + public ProgressIndicator() { + setPreferredSize(baseSize); + + addComponentListener(new ComponentAdapter() { + + @Override + public void componentShown(ComponentEvent e) { + startAnimation(); + } + + + @Override + public void componentHidden(ComponentEvent e) { + stopAnimation(); + } + }); + } + + + public void animateOnce() { + if ((alpha += (speed / 1000)) >= 1) { + alpha -= Math.floor(alpha); + } + } + + + @Override + public void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + + double a = Math.min(getWidth(), getHeight()); + + g2d.scale(a / baseSize.width, a / baseSize.height); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + frame.setFrame(radius, radius, baseSize.width - radius * 2 - 1, baseSize.height - radius * 2 - 1); + + paintShapes(g2d); + } + + + private void paintShapes(Graphics2D g2d) { + circle.setFrame(frame); + + g2d.setStroke(stroke); + g2d.setPaint(backgroundShapeColor); + + g2d.draw(circle); + + Point2D center = new Point2D.Double(frame.getCenterX(), frame.getMinY()); + + circle.setFrameFromCenter(center, new Point2D.Double(center.getX() + radius, center.getY() + radius)); + + g2d.setStroke(stroke); + g2d.setPaint(progressShapeColor); + + // base rotation + g2d.rotate(getTheta(alpha, 1.0), frame.getCenterX(), frame.getCenterY()); + + double theta = getTheta(1, shapeCount); + + for (int i = 0; i < shapeCount; i++) { + g2d.rotate(theta, frame.getCenterX(), frame.getCenterY()); + g2d.fill(circle); + } + } + + + private double getTheta(double value, double max) { + return (value / max) * 2 * Math.PI; + } + + + public void startAnimation() { + if (updateTimer == null) { + updateTimer = new Timer(20, new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + animateOnce(); + repaint(); + } + }); + + updateTimer.start(); + } + } + + + public void stopAnimation() { + if (updateTimer != null) { + updateTimer.stop(); + updateTimer = null; + } + } + + + public void setShapeCount(int indeterminateShapeCount) { + this.shapeCount = indeterminateShapeCount; + } + + + public void setSpeed(double speed) { + this.speed = speed; + } + + + public double getSpeed() { + return speed; + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/RoundBorder.java b/source/net/sourceforge/filebot/util/ui/RoundBorder.java new file mode 100644 index 00000000..e74ecab0 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/RoundBorder.java @@ -0,0 +1,73 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.RenderingHints; + +import javax.swing.border.AbstractBorder; + + +public class RoundBorder extends AbstractBorder { + + private final Color color; + private final Insets insets; + private final int arc; + + + public RoundBorder() { + this.color = new Color(0xACACAC); + this.arc = 12; + this.insets = new Insets(1, 1, 1, 1); + } + + + public RoundBorder(Color color, int arc, Insets insets) { + this.color = color; + this.arc = arc; + this.insets = insets; + } + + + @Override + public boolean isBorderOpaque() { + return false; + } + + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + Graphics2D g2d = (Graphics2D) g.create(); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + g2d.setPaint(c.getBackground()); + g2d.fillRoundRect(x, y, width - 1, height - 1, arc, arc); + + g2d.setPaint(color); + g2d.drawRoundRect(x, y, width - 1, height - 1, arc, arc); + + g2d.dispose(); + } + + + @Override + public Insets getBorderInsets(Component c) { + return new Insets(insets.top, insets.left, insets.bottom, insets.right); + } + + + @Override + public Insets getBorderInsets(Component c, Insets insets) { + insets.top = this.insets.top; + insets.left = this.insets.left; + insets.bottom = this.insets.bottom; + insets.right = this.insets.right; + + return insets; + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/SelectButton.java b/source/net/sourceforge/filebot/util/ui/SelectButton.java new file mode 100644 index 00000000..4340cc5e --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/SelectButton.java @@ -0,0 +1,249 @@ +package net.sourceforge.filebot.util.ui; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.geom.GeneralPath; +import java.awt.geom.Path2D; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.DefaultSingleSelectionModel; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.SingleSelectionModel; +import javax.swing.SwingConstants; + +public class SelectButton extends JButton { + + public static final String SELECTED_VALUE = "selected value"; + + private final Color beginColor = new Color(0xF0EEE4); + private final Color endColor = new Color(0xE0DED4); + + private final Color beginColorHover = beginColor; + private final Color endColorHover = new Color(0xD8D7CD); + + private final SelectIcon selectIcon = new SelectIcon(); + + private List model = Collections.emptyList(); + private SingleSelectionModel selectionModel = new DefaultSingleSelectionModel(); + + private LabelProvider labelProvider = new NullLabelProvider(); + + private boolean hover = false; + + public SelectButton() { + setContentAreaFilled(false); + setFocusable(false); + + super.setIcon(selectIcon); + + setHorizontalAlignment(SwingConstants.CENTER); + setVerticalAlignment(SwingConstants.CENTER); + + setBorder(BorderFactory.createLineBorder(new Color(0xA4A4A4), 1)); + setPreferredSize(new Dimension(32, 22)); + + addActionListener(new OpenPopupOnClick()); + } + + public void setModel(Collection model) { + this.model = new ArrayList(model); + setSelectedIndex(0); + } + + public LabelProvider getLabelProvider() { + return labelProvider; + } + + public void setLabelProvider(LabelProvider labelProvider) { + this.labelProvider = labelProvider; + + // update icon + this.setIcon(labelProvider.getIcon(getSelectedValue())); + } + + @Override + public void setIcon(Icon icon) { + selectIcon.setInnerIcon(icon); + repaint(); + } + + public void setSelectedValue(T value) { + setSelectedIndex(model.indexOf(value)); + } + + public T getSelectedValue() { + if (!selectionModel.isSelected()) + return null; + + return model.get(selectionModel.getSelectedIndex()); + } + + public void setSelectedIndex(int i) { + if (i < 0 || i >= model.size()) { + selectionModel.clearSelection(); + setIcon(null); + return; + } + + selectionModel.setSelectedIndex(i); + T value = model.get(i); + setIcon(labelProvider.getIcon(value)); + firePropertyChange(SELECTED_VALUE, null, value); + } + + public int getSelectedIndex() { + return selectionModel.getSelectedIndex(); + } + + public SingleSelectionModel getSelectionModel() { + return selectionModel; + } + + public void spinValue(int spin) { + int size = model.size(); + + spin = spin % size; + + int next = getSelectedIndex() + spin; + + if (next < 0) + next += size; + else if (next >= size) + next -= size; + + setSelectedIndex(next); + } + + @Override + protected void paintComponent(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + Rectangle bounds = new Rectangle(getSize()); + + if (hover) + g2d.setPaint(GradientStyle.TOP_TO_BOTTOM.getGradientPaint(bounds, beginColorHover, endColorHover)); + else + g2d.setPaint(GradientStyle.TOP_TO_BOTTOM.getGradientPaint(bounds, beginColor, endColor)); + + g2d.fill(bounds); + + super.paintComponent(g); + } + + @Override + protected void processMouseEvent(MouseEvent e) { + switch (e.getID()) { + case MouseEvent.MOUSE_ENTERED: + hover = true; + repaint(); + break; + case MouseEvent.MOUSE_EXITED: + hover = false; + repaint(); + break; + } + + super.processMouseEvent(e); + } + + private class OpenPopupOnClick implements ActionListener { + + @Override + public void actionPerformed(ActionEvent e) { + JPopupMenu popup = new JPopupMenu(); + + for (T value : model) { + SelectPopupMenuItem item = new SelectPopupMenuItem(labelProvider.getText(value), labelProvider.getIcon(value), value); + + if (value == getSelectedValue()) + item.setSelected(true); + + popup.add(item); + } + + popup.show(SelectButton.this, 0, getHeight() - 1); + } + } + + private class SelectPopupMenuItem extends JMenuItem implements ActionListener { + + private final T value; + + public SelectPopupMenuItem(String text, Icon icon, T value) { + super(text, icon); + + this.value = value; + + setMargin(new Insets(3, 0, 3, 0)); + addActionListener(this); + } + + @Override + public void setSelected(boolean selected) { + setFont(getFont().deriveFont(selected ? Font.BOLD : Font.PLAIN)); + } + + @Override + public void actionPerformed(ActionEvent e) { + setSelectedValue(value); + } + + } + + private static class SelectIcon implements Icon { + + private final GeneralPath arrow; + + private Icon icon; + + public SelectIcon() { + arrow = new GeneralPath(Path2D.WIND_EVEN_ODD, 3); + int x = 25; + int y = 10; + + arrow.moveTo(x - 2, y); + arrow.lineTo(x, y + 3); + arrow.lineTo(x + 3, y); + arrow.lineTo(x - 2, y); + } + + public void setInnerIcon(Icon icon) { + this.icon = icon; + } + + public void paintIcon(Component c, Graphics g, int x, int y) { + Graphics2D g2d = (Graphics2D) g; + + if (icon != null) { + icon.paintIcon(c, g2d, 4, 3); + } + + g2d.setPaint(Color.BLACK); + g2d.fill(arrow); + } + + public int getIconWidth() { + return 30; + } + + public int getIconHeight() { + return 20; + } + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/ShadowBorder.java b/source/net/sourceforge/filebot/util/ui/ShadowBorder.java new file mode 100644 index 00000000..3e77d069 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/ShadowBorder.java @@ -0,0 +1,140 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.RadialGradientPaint; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RectangularShape; + +import javax.swing.border.AbstractBorder; + + +public class ShadowBorder extends AbstractBorder { + + private int smoothness; + + private int smoothnessOffset; + + private int offset; + + + public ShadowBorder() { + this(2, 2, 12); + } + + + public ShadowBorder(int offset, int smoothness, int smoothnessOffset) { + this.offset = offset; + this.smoothness = smoothness; + this.smoothnessOffset = smoothnessOffset; + } + + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + Graphics2D g2d = (Graphics2D) g; + + Color bg = new Color(0, 0, 0, 81); + Color faded = new Color(0, 0, 0, 0); + + int a = smoothness + smoothnessOffset; + + Rectangle2D main = new Rectangle2D.Double(a, a, width - a * 2, height - a * 2); + + g2d.setPaint(bg); + g2d.fill(main); + + Rectangle2D right = new Rectangle2D.Double(main.getMaxX(), a, a, main.getHeight()); + Rectangle2D left = new Rectangle2D.Double(0, a, a, main.getHeight()); + Rectangle2D top = new Rectangle2D.Double(a, 0, main.getWidth(), a); + Rectangle2D bottom = new Rectangle2D.Double(a, main.getMaxY(), main.getWidth(), a); + + g2d.setPaint(GradientStyle.LEFT_TO_RIGHT.getGradientPaint(right, bg, faded)); + g2d.fill(right); + + g2d.setPaint(GradientStyle.RIGHT_TO_LEFT.getGradientPaint(left, bg, faded)); + g2d.fill(left); + + g2d.setPaint(GradientStyle.BOTTOM_TO_TOP.getGradientPaint(top, bg, faded)); + g2d.fill(top); + + g2d.setPaint(GradientStyle.TOP_TO_BOTTOM.getGradientPaint(bottom, bg, faded)); + g2d.fill(bottom); + + Rectangle2D topLeftCorner = new Rectangle2D.Double(0, 0, a, a); + Rectangle2D topRightCorner = new Rectangle2D.Double(width - a, 0, a, a); + Rectangle2D bottomLeftCorner = new Rectangle2D.Double(0, height - a, a, a); + Rectangle2D bottomRightCorner = new Rectangle2D.Double(width - a, height - a, a, a); + + g2d.setPaint(CornerGradientStyle.TOP_LEFT.getGradientPaint(topLeftCorner, a, bg, faded)); + g2d.fill(topLeftCorner); + + g2d.setPaint(CornerGradientStyle.TOP_RIGHT.getGradientPaint(topRightCorner, a, bg, faded)); + g2d.fill(topRightCorner); + + g2d.setPaint(CornerGradientStyle.BOTTOM_LEFT.getGradientPaint(bottomLeftCorner, a, bg, faded)); + g2d.fill(bottomLeftCorner); + + g2d.setPaint(CornerGradientStyle.BOTTOM_RIGHT.getGradientPaint(bottomRightCorner, a, bg, faded)); + g2d.fill(bottomRightCorner); + } + + + @Override + public Insets getBorderInsets(Component c) { + return getBorderInsets(c, new Insets(0, 0, 0, 0)); + } + + + @Override + public Insets getBorderInsets(Component c, Insets insets) { + insets.top = insets.left = Math.max(smoothness - offset, 4); + insets.bottom = insets.right = Math.max(smoothness + offset, 4); + return insets; + } + + + private static enum CornerGradientStyle { + TOP_LEFT, + TOP_RIGHT, + BOTTOM_LEFT, + BOTTOM_RIGHT; + + public RadialGradientPaint getGradientPaint(RectangularShape shape, float radius, Color gradientBeginColor, Color gradientEndColor) { + Point2D center = null; + + switch (this) { + case TOP_LEFT: + center = new Point2D.Double(shape.getX() + radius, shape.getY() + radius); + break; + + case TOP_RIGHT: + center = new Point2D.Double(shape.getX() + 0, shape.getY() + radius); + break; + + case BOTTOM_LEFT: + center = new Point2D.Double(shape.getX() + radius, shape.getY() + 0); + break; + + case BOTTOM_RIGHT: + center = new Point2D.Double(shape.getX() + 0, shape.getY() + 0); + break; + + default: + return null; + } + + float[] dist = { 0.0f, 1.0f }; + Color[] colors = { gradientBeginColor, gradientEndColor }; + + return new RadialGradientPaint(center, radius, dist, colors); + } + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/SimpleLabelProvider.java b/source/net/sourceforge/filebot/util/ui/SimpleLabelProvider.java new file mode 100644 index 00000000..e3d1c944 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/SimpleLabelProvider.java @@ -0,0 +1,90 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.lang.reflect.Method; +import java.util.Arrays; + +import javax.swing.Icon; + +import net.sourceforge.filebot.util.ExceptionUtilities; + + +/** + * LabelProvider based on reflection. + */ +public class SimpleLabelProvider implements LabelProvider { + + private final Method getIconMethod; + private final Method getTextMethod; + + + /** + * Factory method for {@link #SimpleLabelProvider(Class)}. + * + * @return new LabelProvider + */ + public static SimpleLabelProvider forClass(Class type) { + return new SimpleLabelProvider(type); + } + + + /** + * Create a new LabelProvider which will use the getText, getName or toString + * method for text and the getIcon method for the + * icon. + * + * @param type a class that has one of the text methods and the icon method + */ + public SimpleLabelProvider(Class type) { + getTextMethod = findAnyMethod(type, "getText", "getName", "toString"); + getIconMethod = findAnyMethod(type, "getIcon"); + } + + + /** + * Create a new LabelProvider which will use a specified method of a given class + * + * @param type a class with the specified method + * @param getText a method name such as getText + * @param getIcon a method name such as getIcon + */ + public SimpleLabelProvider(Class type, String getText, String getIcon) { + getTextMethod = findAnyMethod(type, getText); + getIconMethod = findAnyMethod(type, getIcon); + } + + + private Method findAnyMethod(Class type, String... names) { + for (String name : names) { + try { + return type.getMethod(name); + } catch (NoSuchMethodException e) { + // try next method name + } + } + + throw new IllegalArgumentException("Method not found: " + Arrays.toString(names)); + } + + + @Override + public String getText(T value) { + try { + return (String) getTextMethod.invoke(value); + } catch (Exception e) { + throw ExceptionUtilities.asRuntimeException(e); + } + } + + + @Override + public Icon getIcon(T value) { + try { + return (Icon) getIconMethod.invoke(value); + } catch (Exception e) { + throw ExceptionUtilities.asRuntimeException(e); + } + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/SwingWorkerPropertyChangeAdapter.java b/source/net/sourceforge/filebot/util/ui/SwingWorkerPropertyChangeAdapter.java new file mode 100644 index 00000000..b6f01fb0 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/SwingWorkerPropertyChangeAdapter.java @@ -0,0 +1,51 @@ + +package net.sourceforge.filebot.util.ui; + + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.SwingWorker.StateValue; + + +public abstract class SwingWorkerPropertyChangeAdapter implements PropertyChangeListener { + + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals("progress")) { + progress(evt); + } else if (evt.getPropertyName().equals("state")) { + state(evt); + } else { + event(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue()); + } + } + + + protected void state(PropertyChangeEvent evt) { + switch ((StateValue) evt.getNewValue()) { + case STARTED: + started(evt); + break; + case DONE: + done(evt); + break; + } + } + + + protected void progress(PropertyChangeEvent evt) { + } + + + protected void started(PropertyChangeEvent evt) { + } + + + protected void done(PropertyChangeEvent evt) { + } + + + protected void event(String name, Object oldValue, Object newValue) { + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/TunedUtilities.java b/source/net/sourceforge/filebot/util/ui/TunedUtilities.java new file mode 100644 index 00000000..92f11656 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/TunedUtilities.java @@ -0,0 +1,280 @@ +package net.sourceforge.filebot.util.ui; + +import static java.util.Collections.*; +import static javax.swing.JOptionPane.*; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Point; +import java.awt.Window; +import java.awt.dnd.DnDConstants; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.image.BufferedImage; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JOptionPane; +import javax.swing.KeyStroke; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.basic.BasicTableUI; +import javax.swing.text.JTextComponent; +import javax.swing.undo.UndoManager; + +public final class TunedUtilities { + + public static final Color TRANSLUCENT = new Color(255, 255, 255, 0); + + public static void checkEventDispatchThread() { + if (!SwingUtilities.isEventDispatchThread()) { + throw new IllegalStateException("Method must be accessed from the Swing Event Dispatch Thread, but was called on Thread \"" + Thread.currentThread().getName() + "\""); + } + } + + public static Color interpolateHSB(Color c1, Color c2, float f) { + float[] hsb1 = Color.RGBtoHSB(c1.getRed(), c1.getGreen(), c1.getBlue(), null); + float[] hsb2 = Color.RGBtoHSB(c2.getRed(), c2.getGreen(), c2.getBlue(), null); + float[] hsb = new float[3]; + + for (int i = 0; i < hsb.length; i++) { + hsb[i] = hsb1[i] + ((hsb2[i] - hsb1[i]) * f); + } + + return Color.getHSBColor(hsb[0], hsb[1], hsb[2]); + } + + public static String escapeHTML(String s) { + char[] sc = new char[] { '&', '<', '>', '"', '\'' }; + for (char c : sc) { + s = s.replace(Character.toString(c), String.format("&#%d;", (int) c)); // e.g. & + } + return s; + } + + public static Color derive(Color color, float alpha) { + return new Color(((int) ((alpha * 255)) << 24) | (color.getRGB() & 0x00FFFFFF), true); + } + + public static String toHex(Color c) { + return String.format("#%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue()); + } + + public static boolean isShiftOrAltDown(ActionEvent evt) { + return checkModifiers(evt.getModifiers(), ActionEvent.SHIFT_MASK) || checkModifiers(evt.getModifiers(), ActionEvent.ALT_MASK); + } + + public static boolean checkModifiers(int modifiers, int mask) { + return ((modifiers & mask) == mask); + } + + public static JButton createImageButton(Action action) { + JButton button = new JButton(action); + button.setHideActionText(true); + button.setOpaque(false); + + return button; + } + + public static void installAction(JComponent component, KeyStroke keystroke, Action action) { + Object key = action.getValue(Action.NAME); + + if (key == null) + throw new IllegalArgumentException("Action must have a name"); + + component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(keystroke, key); + component.getActionMap().put(key, action); + } + + public static UndoManager installUndoSupport(JTextComponent component) { + final UndoManager undoSupport = new UndoManager(); + + // install undo listener + component.getDocument().addUndoableEditListener(undoSupport); + + // install undo action + installAction(component, KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_MASK), new AbstractAction("Undo") { + + @Override + public void actionPerformed(ActionEvent e) { + if (undoSupport.canUndo()) + undoSupport.undo(); + } + }); + + // install redo action + installAction(component, KeyStroke.getKeyStroke(KeyEvent.VK_Y, KeyEvent.CTRL_MASK), new AbstractAction("Redo") { + + @Override + public void actionPerformed(ActionEvent e) { + if (undoSupport.canRedo()) + undoSupport.redo(); + } + }); + + return undoSupport; + } + + public static boolean isMaximized(Frame frame) { + return (frame.getExtendedState() & Frame.MAXIMIZED_BOTH) != 0; + } + + public static List showMultiValueInputDialog(final String text, final String initialValue, final String title, final Component parent) throws InvocationTargetException, InterruptedException { + String input = showInputDialog(text, initialValue, title, parent); + if (input == null || input.isEmpty()) { + return emptyList(); + } + + for (char separator : new char[] { '|', ';' }) { + if (input.indexOf(separator) >= 0) { + List values = new ArrayList(); + for (String field : input.split(Pattern.quote(Character.toString(separator)))) { + field = field.trim(); + + if (field.length() > 0) { + values.add(field); + } + } + + if (values.size() > 0) { + return values; + } + } + } + + return singletonList(input); + } + + public static String showInputDialog(final String text, final String initialValue, final String title, final Component parent) throws InvocationTargetException, InterruptedException { + final StringBuilder buffer = new StringBuilder(); + + Runnable runnable = new Runnable() { + + @Override + public void run() { + Object value = JOptionPane.showInputDialog(parent, text, title, PLAIN_MESSAGE, null, null, initialValue); + if (value != null) { + buffer.append(value.toString().trim()); + } + } + }; + if (SwingUtilities.isEventDispatchThread()) { + runnable.run(); + } else { + SwingUtilities.invokeAndWait(runnable); + } + + return buffer.length() == 0 ? null : buffer.toString(); + } + + public static Window getWindow(Object component) { + if (component instanceof Window) + return (Window) component; + + if (component instanceof Component) + return SwingUtilities.getWindowAncestor((Component) component); + + return null; + } + + public static Point getOffsetLocation(Window owner) { + if (owner == null) { + Window[] toplevel = Window.getOwnerlessWindows(); + + if (toplevel.length == 0) + return new Point(120, 80); + + // assume first top-level window as point of reference + owner = toplevel[0]; + } + + Point p = owner.getLocation(); + Dimension d = owner.getSize(); + + return new Point(p.x + d.width / 4, p.y + d.height / 7); + } + + public static Image getImage(Icon icon) { + if (icon == null) + return null; + + if (icon instanceof ImageIcon) + return ((ImageIcon) icon).getImage(); + + // draw icon into a new image + BufferedImage image = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB); + + Graphics2D g2d = image.createGraphics(); + icon.paintIcon(null, g2d, 0, 0); + g2d.dispose(); + + return image; + } + + public static Dimension getDimension(Icon icon) { + return new Dimension(icon.getIconWidth(), icon.getIconHeight()); + } + + public static Timer invokeLater(int delay, final Runnable runnable) { + Timer timer = new Timer(delay, new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + runnable.run(); + } + }); + + timer.setRepeats(false); + timer.start(); + + return timer; + } + + /** + * When trying to drag a row of a multi-select JTable, it will start selecting rows instead of initiating a drag. This TableUI will give the JTable proper dnd behaviour. + */ + public static class DragDropRowTableUI extends BasicTableUI { + + @Override + protected MouseInputListener createMouseInputListener() { + return new DragDropRowMouseInputHandler(); + } + + protected class DragDropRowMouseInputHandler extends MouseInputHandler { + + @Override + public void mouseDragged(MouseEvent e) { + // Only do special handling if we are drag enabled with multiple selection + if (table.getDragEnabled() && table.getSelectionModel().getSelectionMode() == ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) { + table.getTransferHandler().exportAsDrag(table, e, DnDConstants.ACTION_COPY); + } else { + super.mouseDragged(e); + } + } + } + } + + /** + * Dummy constructor to prevent instantiation. + */ + private TunedUtilities() { + throw new UnsupportedOperationException(); + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/notification/Direction.java b/source/net/sourceforge/filebot/util/ui/notification/Direction.java new file mode 100644 index 00000000..efb5b737 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/notification/Direction.java @@ -0,0 +1,33 @@ + +package net.sourceforge.filebot.util.ui.notification; + + +import javax.swing.SwingConstants; + + +public enum Direction { + CENTER(0, 0, 0.5, 0.5, SwingConstants.CENTER), + NORTH(0, -1, 0.5, 0.0, SwingConstants.NORTH), + NORTH_EAST(1, -1, 1.0, 0.0, SwingConstants.NORTH_EAST), + EAST(1, 0, 1.0, 0.5, SwingConstants.EAST), + SOUTH_EAST(1, 1, 1.0, 1.0, SwingConstants.SOUTH_EAST), + SOUTH(0, 1, 0.5, 1.0, SwingConstants.SOUTH), + SOUTH_WEST(-1, 1, 0.0, 1.0, SwingConstants.SOUTH_WEST), + WEST(-1, 0, 0.0, 0.5, SwingConstants.WEST), + NORTH_WEST(-1, -1, 0.0, 0.0, SwingConstants.NORTH_WEST); + + public final int vx; + public final int vy; + public final double ax; + public final double ay; + public final int swingConstant; + + + private Direction(int vx, int vy, double ax, double ay, int swingConstant) { + this.vx = vx; + this.vy = vy; + this.ax = ax; + this.ay = ay; + this.swingConstant = swingConstant; + } +} diff --git a/source/net/sourceforge/filebot/util/ui/notification/MessageNotification.java b/source/net/sourceforge/filebot/util/ui/notification/MessageNotification.java new file mode 100644 index 00000000..ccddec03 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/notification/MessageNotification.java @@ -0,0 +1,77 @@ +/* + * Created on 16.03.2005 + */ + +package net.sourceforge.filebot.util.ui.notification; + + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Font; +import java.awt.Window; + +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextPane; +import javax.swing.SwingConstants; +import javax.swing.border.Border; + + +public class MessageNotification extends NotificationWindow { + + public MessageNotification(String head, String text, Icon icon, int timeout) { + this((Window) null, head, text, icon, timeout); + } + + + public MessageNotification(String head, String text, Icon icon) { + this(head, text, icon, -1); + } + + private int margin = 10; + private Border marginBorder = BorderFactory.createEmptyBorder(margin, margin, margin, margin); + private Border border = BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(new Color(245, 155, 15), Color.WHITE), marginBorder); + + private JLabel headLabel; + private JTextPane textArea; + private JLabel imageLabel; + + + public MessageNotification(Window owner, String head, String text, Icon icon, int timeout) { + super(owner, timeout); + + JComponent c = (JComponent) getContentPane(); + + c.setLayout(new BorderLayout(5, 2)); + c.setBackground(Color.WHITE); + c.setBorder(border); + + JPanel textPanel = new JPanel(new BorderLayout()); + textPanel.setOpaque(false); + textPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); + + headLabel = new JLabel(head); + headLabel.setHorizontalAlignment(SwingConstants.CENTER); + headLabel.setFont(headLabel.getFont().deriveFont(Font.BOLD)); + textPanel.add(headLabel, BorderLayout.NORTH); + + textArea = new JTextPane(); + textArea.setText(text); + textArea.setEditable(false); + textArea.setOpaque(false); + textPanel.add(textArea, BorderLayout.CENTER); + + if (icon != null) { + imageLabel = new JLabel(icon); + c.add(imageLabel, BorderLayout.WEST); + } + + c.add(textPanel, BorderLayout.CENTER); + + pack(); + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/notification/NotificationLayout.java b/source/net/sourceforge/filebot/util/ui/notification/NotificationLayout.java new file mode 100644 index 00000000..16a7ce23 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/notification/NotificationLayout.java @@ -0,0 +1,14 @@ +/* + * Created on 19.03.2005 + */ + +package net.sourceforge.filebot.util.ui.notification; + + +public interface NotificationLayout { + + public void add(NotificationWindow notification); + + + public void remove(NotificationWindow notification); +} diff --git a/source/net/sourceforge/filebot/util/ui/notification/NotificationManager.java b/source/net/sourceforge/filebot/util/ui/notification/NotificationManager.java new file mode 100644 index 00000000..80427623 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/notification/NotificationManager.java @@ -0,0 +1,47 @@ +/* + * Created on 19.03.2005 + */ + +package net.sourceforge.filebot.util.ui.notification; + + +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import net.sourceforge.filebot.util.ui.TunedUtilities; + + +public class NotificationManager { + + private final NotificationLayout layout; + + + public NotificationManager() { + this(new QueueNotificationLayout()); + } + + + public NotificationManager(NotificationLayout layout) { + this.layout = layout; + } + + + public void show(NotificationWindow notification) { + TunedUtilities.checkEventDispatchThread(); + + notification.addWindowListener(new RemoveListener()); + layout.add(notification); + + notification.setVisible(true); + } + + + private class RemoveListener extends WindowAdapter { + + @Override + public void windowClosing(WindowEvent e) { + layout.remove((NotificationWindow) e.getWindow()); + } + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/notification/NotificationWindow.java b/source/net/sourceforge/filebot/util/ui/notification/NotificationWindow.java new file mode 100644 index 00000000..1262f541 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/notification/NotificationWindow.java @@ -0,0 +1,102 @@ +/* + * Created on 19.03.2005 + */ + +package net.sourceforge.filebot.util.ui.notification; + + +import java.awt.Window; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowEvent; + +import javax.swing.JWindow; +import javax.swing.Timer; + +import net.sourceforge.filebot.util.ui.TunedUtilities; + + +public class NotificationWindow extends JWindow { + + private final int timeout; + + + public NotificationWindow(Window owner, int timeout) { + this(owner, timeout, true); + } + + + public NotificationWindow(Window owner, int timeout, boolean closeOnClick) { + super(owner); + this.timeout = timeout; + + setAlwaysOnTop(true); + + if (closeOnClick) { + getGlassPane().addMouseListener(clickListener); + getGlassPane().setVisible(true); + } + + addComponentListener(closeOnTimeout); + } + + + public NotificationWindow(Window owner) { + this(owner, -1); + } + + + public final void close() { + TunedUtilities.checkEventDispatchThread(); + + // window events are not fired automatically, required for layout updates + processWindowEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING)); + + setVisible(false); + + // component events are not fired automatically, used to cancel timeout timer + processComponentEvent(new ComponentEvent(this, ComponentEvent.COMPONENT_HIDDEN)); + + dispose(); + } + + private final ComponentListener closeOnTimeout = new ComponentAdapter() { + + private Timer timer = null; + + + @Override + public void componentShown(ComponentEvent e) { + if (timeout >= 0) { + timer = TunedUtilities.invokeLater(timeout, new Runnable() { + + @Override + public void run() { + close(); + } + }); + } + } + + + @Override + public void componentHidden(ComponentEvent e) { + if (timer != null) { + timer.stop(); + } + } + + }; + + private final MouseAdapter clickListener = new MouseAdapter() { + + @Override + public void mouseClicked(MouseEvent e) { + close(); + } + }; + +} diff --git a/source/net/sourceforge/filebot/util/ui/notification/QueueNotificationLayout.java b/source/net/sourceforge/filebot/util/ui/notification/QueueNotificationLayout.java new file mode 100644 index 00000000..a0dea517 --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/notification/QueueNotificationLayout.java @@ -0,0 +1,112 @@ +/* + * Created on 19.03.2005 + */ + +package net.sourceforge.filebot.util.ui.notification; + + +import static net.sourceforge.filebot.util.ui.notification.Direction.*; + +import java.awt.Dimension; +import java.awt.GraphicsConfiguration; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Toolkit; +import java.util.ArrayList; +import java.util.List; + + +public class QueueNotificationLayout implements NotificationLayout { + + private final List notifications = new ArrayList(); + + private final Direction alignment; + private final Direction direction; + private final Direction growAnchor; + + + public QueueNotificationLayout() { + this(SOUTH_EAST, WEST); + } + + + public QueueNotificationLayout(Direction alignment, Direction direction) { + this.alignment = alignment; + this.growAnchor = alignment; + this.direction = direction; + } + + + public QueueNotificationLayout(Direction orientation, Direction direction, Direction growAnchor) { + this.alignment = orientation; + this.direction = direction; + this.growAnchor = growAnchor; + } + + + private Point getBaseAnchor(Dimension screen, Insets insets) { + Point p = new Point(); + + screen.height -= insets.top + insets.bottom; + screen.width -= insets.left + insets.right; + + p.x = (int) (alignment.ax * screen.width); + p.y = (int) (alignment.ay * screen.height); + + p.x += insets.left; + p.y += insets.top; + + return p; + } + + + private Point getLocation(Point anchor, Dimension size) { + Point p = new Point(); + + p.x = (int) (anchor.x - size.width * growAnchor.ax); + p.y = (int) (anchor.y - size.height * growAnchor.ay); + + return p; + } + + + private Point getNextAnchor(Point anchor, Dimension size) { + Point p = new Point(); + + p.x = anchor.x + size.width * direction.vx; + p.y = anchor.y + size.height * direction.vy; + + return p; + } + + + public void add(NotificationWindow notification) { + notifications.add(notification); + align(notification.getGraphicsConfiguration()); + } + + + private void align(GraphicsConfiguration gc) { + Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); + + Point anchor = getBaseAnchor(screen, insets); + + for (NotificationWindow window : notifications) { + Dimension size = window.getSize(); + + Point p = getLocation(anchor, size); + window.setLocation(p); + + anchor = getNextAnchor(anchor, size); + } + } + + + public void remove(NotificationWindow notification) { + if (notifications.remove(notification)) { + align(notification.getGraphicsConfiguration()); + } + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/notification/SeparatorBorder.java b/source/net/sourceforge/filebot/util/ui/notification/SeparatorBorder.java new file mode 100644 index 00000000..e55d390b --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/notification/SeparatorBorder.java @@ -0,0 +1,173 @@ + +package net.sourceforge.filebot.util.ui.notification; + + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RectangularShape; + +import javax.swing.border.AbstractBorder; + +import net.sourceforge.filebot.util.ui.GradientStyle; + + +public class SeparatorBorder extends AbstractBorder { + + private int borderWidth; + + private Color beginColor; + + private Color endColor; + + private GradientStyle gradientStyle; + + private Position position; + + + public static enum Position { + TOP, + BOTTOM, + LEFT, + RIGHT; + + public Rectangle2D getRectangle(RectangularShape shape, int borderWidth) { + switch (this) { + case TOP: + return new Rectangle2D.Double(shape.getX(), shape.getY(), shape.getWidth(), borderWidth); + case BOTTOM: + return new Rectangle2D.Double(shape.getX(), shape.getMaxY() - borderWidth, shape.getWidth(), borderWidth); + case LEFT: + return new Rectangle2D.Double(shape.getX(), shape.getY(), borderWidth, shape.getHeight()); + case RIGHT: + return new Rectangle2D.Double(shape.getMaxX() - borderWidth, shape.getY(), borderWidth, shape.getHeight()); + default: + return null; + } + } + + + public Insets getInsets(Insets insets, int borderWidth) { + switch (this) { + case TOP: + insets.top = borderWidth; + insets.left = insets.right = insets.bottom = 0; + return insets; + case BOTTOM: + insets.bottom = borderWidth; + insets.left = insets.right = insets.top = 0; + return insets; + case LEFT: + insets.left = borderWidth; + insets.right = insets.top = insets.bottom = 0; + return insets; + case RIGHT: + insets.right = borderWidth; + insets.left = insets.top = insets.bottom = 0; + return insets; + default: + return null; + } + } + } + + + public SeparatorBorder(int height, Color color, Position position) { + this(height, color, null, null, position); + } + + + public SeparatorBorder(int height, Color color, GradientStyle gradientStyle, Position position) { + this(height, color, new Color(color.getRed(), color.getGreen(), color.getBlue(), 0), gradientStyle, position); + } + + + public SeparatorBorder(int height, Color beginColor, Color endColor, GradientStyle gradientStyle, Position position) { + this.borderWidth = height; + this.beginColor = beginColor; + this.endColor = endColor; + this.gradientStyle = gradientStyle; + this.position = position; + } + + + @Override + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + Graphics2D g2d = (Graphics2D) g; + + Rectangle2D shape = position.getRectangle(new Rectangle2D.Double(x, y, width, height), this.borderWidth); + + if (gradientStyle != null && endColor != null) + g2d.setPaint(gradientStyle.getGradientPaint(shape, beginColor, endColor)); + else + g2d.setPaint(beginColor); + + g2d.fill(shape); + } + + + @Override + public Insets getBorderInsets(Component c) { + return getBorderInsets(c, new Insets(0, 0, 0, 0)); + } + + + @Override + public Insets getBorderInsets(Component c, Insets insets) { + return position.getInsets(insets, borderWidth); + } + + + public Color getBeginColor() { + return beginColor; + } + + + public void setBeginColor(Color beginColor) { + this.beginColor = beginColor; + } + + + public Color getEndColor() { + return endColor; + } + + + public void setEndColor(Color endColor) { + this.endColor = endColor; + } + + + public GradientStyle getGradientStyle() { + return gradientStyle; + } + + + public void setGradientStyle(GradientStyle gradientStyle) { + this.gradientStyle = gradientStyle; + } + + + public int getBorderWidth() { + return borderWidth; + } + + + public void setBorderWidth(int height) { + this.borderWidth = height; + } + + + public Position getPosition() { + return position; + } + + + public void setPosition(Position position) { + this.position = position; + } + +} diff --git a/source/net/sourceforge/filebot/util/ui/notification/SimpleNotificationLayout.java b/source/net/sourceforge/filebot/util/ui/notification/SimpleNotificationLayout.java new file mode 100644 index 00000000..593c2bcc --- /dev/null +++ b/source/net/sourceforge/filebot/util/ui/notification/SimpleNotificationLayout.java @@ -0,0 +1,78 @@ +/* + * Created on 20.03.2005 + */ + +package net.sourceforge.filebot.util.ui.notification; + + +import static net.sourceforge.filebot.util.ui.notification.Direction.*; + +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Toolkit; + + +public class SimpleNotificationLayout implements NotificationLayout { + + private NotificationWindow currentNotification; + private Direction alignment; + + + public SimpleNotificationLayout() { + this(NORTH); + } + + + public SimpleNotificationLayout(Direction alignment) { + this.alignment = alignment; + } + + + private Point getBaseAnchor(Dimension screen, Insets insets) { + Point p = new Point(); + + screen.height -= insets.top + insets.bottom; + screen.width -= insets.left + insets.right; + + p.x = (int) (alignment.ax * screen.width); + p.y = (int) (alignment.ay * screen.height); + + p.x += insets.left; + p.y += insets.top; + + return p; + } + + + private Point getLocation(Point anchor, Dimension size) { + Point p = new Point(); + + p.x = (int) (anchor.x - size.width * alignment.ax); + p.y = (int) (anchor.y - size.height * alignment.ay); + + return p; + } + + + public void add(NotificationWindow notification) { + Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(notification.getGraphicsConfiguration()); + Dimension size = notification.getSize(); + + Point anchor = getBaseAnchor(screen, insets); + notification.setLocation(getLocation(anchor, size)); + + if (currentNotification != null) { + currentNotification.close(); + } + + currentNotification = notification; + } + + + public void remove(NotificationWindow notification) { + + } + +} diff --git a/source/net/sourceforge/filebot/vfs/RarArchive.java b/source/net/sourceforge/filebot/vfs/RarArchive.java index 12715d38..9806fca6 100644 --- a/source/net/sourceforge/filebot/vfs/RarArchive.java +++ b/source/net/sourceforge/filebot/vfs/RarArchive.java @@ -10,7 +10,7 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import net.sourceforge.tuned.ByteBufferOutputStream; +import net.sourceforge.filebot.util.ByteBufferOutputStream; import de.innosystec.unrar.Archive; import de.innosystec.unrar.exception.RarException; import de.innosystec.unrar.rarfile.FileHeader; diff --git a/source/net/sourceforge/filebot/vfs/SimpleFileInfo.java b/source/net/sourceforge/filebot/vfs/SimpleFileInfo.java index 74057d14..84e6a981 100644 --- a/source/net/sourceforge/filebot/vfs/SimpleFileInfo.java +++ b/source/net/sourceforge/filebot/vfs/SimpleFileInfo.java @@ -1,6 +1,6 @@ package net.sourceforge.filebot.vfs; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; import java.util.Arrays; diff --git a/source/net/sourceforge/filebot/vfs/ZipArchive.java b/source/net/sourceforge/filebot/vfs/ZipArchive.java index 8b14730c..03570f39 100644 --- a/source/net/sourceforge/filebot/vfs/ZipArchive.java +++ b/source/net/sourceforge/filebot/vfs/ZipArchive.java @@ -10,8 +10,8 @@ import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import net.sourceforge.tuned.ByteBufferInputStream; -import net.sourceforge.tuned.ByteBufferOutputStream; +import net.sourceforge.filebot.util.ByteBufferInputStream; +import net.sourceforge.filebot.util.ByteBufferOutputStream; public class ZipArchive implements Iterable { diff --git a/source/net/sourceforge/filebot/web/AcoustID.java b/source/net/sourceforge/filebot/web/AcoustID.java index 70ccfd08..b0efac4b 100644 --- a/source/net/sourceforge/filebot/web/AcoustID.java +++ b/source/net/sourceforge/filebot/web/AcoustID.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.web; import static java.util.Collections.*; import static net.sourceforge.filebot.web.WebRequest.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; import java.io.IOException; diff --git a/source/net/sourceforge/filebot/web/AnidbClient.java b/source/net/sourceforge/filebot/web/AnidbClient.java index e48540d5..2f50c3dd 100644 --- a/source/net/sourceforge/filebot/web/AnidbClient.java +++ b/source/net/sourceforge/filebot/web/AnidbClient.java @@ -2,7 +2,7 @@ package net.sourceforge.filebot.web; import static net.sourceforge.filebot.web.EpisodeUtilities.*; import static net.sourceforge.filebot.web.WebRequest.*; -import static net.sourceforge.tuned.XPathUtilities.*; +import static net.sourceforge.filebot.util.XPathUtilities.*; import java.net.URI; import java.net.URISyntaxException; diff --git a/source/net/sourceforge/filebot/web/CachedPage.java b/source/net/sourceforge/filebot/web/CachedPage.java index 104f717e..93a387e8 100644 --- a/source/net/sourceforge/filebot/web/CachedPage.java +++ b/source/net/sourceforge/filebot/web/CachedPage.java @@ -1,7 +1,7 @@ package net.sourceforge.filebot.web; import static net.sourceforge.filebot.web.WebRequest.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.IOException; import java.io.Reader; diff --git a/source/net/sourceforge/filebot/web/EpisodeFormat.java b/source/net/sourceforge/filebot/web/EpisodeFormat.java index 54cdf54c..05a60fb3 100644 --- a/source/net/sourceforge/filebot/web/EpisodeFormat.java +++ b/source/net/sourceforge/filebot/web/EpisodeFormat.java @@ -1,6 +1,6 @@ package net.sourceforge.filebot.web; -import static net.sourceforge.tuned.StringUtilities.*; +import static net.sourceforge.filebot.util.StringUtilities.*; import java.text.FieldPosition; import java.text.Format; diff --git a/source/net/sourceforge/filebot/web/FanartTV.java b/source/net/sourceforge/filebot/web/FanartTV.java index fb6a3628..4a27adcf 100644 --- a/source/net/sourceforge/filebot/web/FanartTV.java +++ b/source/net/sourceforge/filebot/web/FanartTV.java @@ -1,7 +1,7 @@ package net.sourceforge.filebot.web; import static net.sourceforge.filebot.web.WebRequest.*; -import static net.sourceforge.tuned.XPathUtilities.*; +import static net.sourceforge.filebot.util.XPathUtilities.*; import java.io.File; import java.io.Serializable; diff --git a/source/net/sourceforge/filebot/web/IMDbClient.java b/source/net/sourceforge/filebot/web/IMDbClient.java index 5d308ada..15764b4a 100644 --- a/source/net/sourceforge/filebot/web/IMDbClient.java +++ b/source/net/sourceforge/filebot/web/IMDbClient.java @@ -1,7 +1,7 @@ package net.sourceforge.filebot.web; import static net.sourceforge.filebot.web.WebRequest.*; -import static net.sourceforge.tuned.XPathUtilities.*; +import static net.sourceforge.filebot.util.XPathUtilities.*; import java.io.File; import java.io.FileNotFoundException; diff --git a/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java b/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java index 58fa4bf5..bc9773ec 100644 --- a/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java +++ b/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java @@ -4,7 +4,7 @@ import static java.lang.Math.*; import static java.util.Arrays.*; import static java.util.Collections.*; import static net.sourceforge.filebot.web.OpenSubtitlesHasher.*; -import static net.sourceforge.tuned.FileUtilities.*; +import static net.sourceforge.filebot.util.FileUtilities.*; import java.io.File; import java.io.IOException; @@ -39,8 +39,8 @@ import net.sourceforge.filebot.web.OpenSubtitlesXmlRpc.BaseInfo; import net.sourceforge.filebot.web.OpenSubtitlesXmlRpc.Query; import net.sourceforge.filebot.web.OpenSubtitlesXmlRpc.SubFile; import net.sourceforge.filebot.web.OpenSubtitlesXmlRpc.TryUploadResponse; -import net.sourceforge.tuned.ExceptionUtilities; -import net.sourceforge.tuned.Timer; +import net.sourceforge.filebot.util.ExceptionUtilities; +import net.sourceforge.filebot.util.Timer; import redstone.xmlrpc.XmlRpcException; import redstone.xmlrpc.XmlRpcFault; diff --git a/source/net/sourceforge/filebot/web/OpenSubtitlesSubtitleDescriptor.java b/source/net/sourceforge/filebot/web/OpenSubtitlesSubtitleDescriptor.java index 195fb608..1986bd32 100644 --- a/source/net/sourceforge/filebot/web/OpenSubtitlesSubtitleDescriptor.java +++ b/source/net/sourceforge/filebot/web/OpenSubtitlesSubtitleDescriptor.java @@ -12,8 +12,8 @@ import java.util.Map.Entry; import java.util.zip.GZIPInputStream; import java.util.zip.ZipException; -import net.sourceforge.tuned.ByteBufferOutputStream; -import net.sourceforge.tuned.FileUtilities; +import net.sourceforge.filebot.util.ByteBufferOutputStream; +import net.sourceforge.filebot.util.FileUtilities; /** * Describes a subtitle on OpenSubtitles. diff --git a/source/net/sourceforge/filebot/web/OpenSubtitlesXmlRpc.java b/source/net/sourceforge/filebot/web/OpenSubtitlesXmlRpc.java index 13082990..cad55060 100644 --- a/source/net/sourceforge/filebot/web/OpenSubtitlesXmlRpc.java +++ b/source/net/sourceforge/filebot/web/OpenSubtitlesXmlRpc.java @@ -1,7 +1,7 @@ package net.sourceforge.filebot.web; import static java.util.Collections.*; -import static net.sourceforge.tuned.StringUtilities.*; +import static net.sourceforge.filebot.util.StringUtilities.*; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -26,7 +26,7 @@ import java.util.zip.DeflaterInputStream; import java.util.zip.GZIPInputStream; import net.sourceforge.filebot.web.OpenSubtitlesSubtitleDescriptor.Property; -import net.sourceforge.tuned.ByteBufferOutputStream; +import net.sourceforge.filebot.util.ByteBufferOutputStream; import redstone.xmlrpc.XmlRpcClient; import redstone.xmlrpc.XmlRpcException; import redstone.xmlrpc.XmlRpcFault; diff --git a/source/net/sourceforge/filebot/web/TVRageClient.java b/source/net/sourceforge/filebot/web/TVRageClient.java index 9faec6c4..db37a503 100644 --- a/source/net/sourceforge/filebot/web/TVRageClient.java +++ b/source/net/sourceforge/filebot/web/TVRageClient.java @@ -4,7 +4,7 @@ package net.sourceforge.filebot.web; import static net.sourceforge.filebot.web.EpisodeUtilities.*; import static net.sourceforge.filebot.web.WebRequest.*; -import static net.sourceforge.tuned.XPathUtilities.*; +import static net.sourceforge.filebot.util.XPathUtilities.*; import java.io.IOException; import java.net.URI; diff --git a/source/net/sourceforge/filebot/web/TheTVDBClient.java b/source/net/sourceforge/filebot/web/TheTVDBClient.java index 9ab997d5..407f8d86 100644 --- a/source/net/sourceforge/filebot/web/TheTVDBClient.java +++ b/source/net/sourceforge/filebot/web/TheTVDBClient.java @@ -3,7 +3,7 @@ package net.sourceforge.filebot.web; import static java.util.Arrays.*; import static net.sourceforge.filebot.web.EpisodeUtilities.*; import static net.sourceforge.filebot.web.WebRequest.*; -import static net.sourceforge.tuned.XPathUtilities.*; +import static net.sourceforge.filebot.util.XPathUtilities.*; import java.io.FileNotFoundException; import java.io.IOException; @@ -29,7 +29,7 @@ import net.sourceforge.filebot.Cache; import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.web.TheTVDBClient.BannerDescriptor.BannerProperty; import net.sourceforge.filebot.web.TheTVDBClient.SeriesInfo.SeriesProperty; -import net.sourceforge.tuned.FileUtilities; +import net.sourceforge.filebot.util.FileUtilities; import org.w3c.dom.Document; import org.w3c.dom.Node; diff --git a/source/net/sourceforge/filebot/web/WebRequest.java b/source/net/sourceforge/filebot/web/WebRequest.java index 637bfd04..3797e780 100644 --- a/source/net/sourceforge/filebot/web/WebRequest.java +++ b/source/net/sourceforge/filebot/web/WebRequest.java @@ -34,7 +34,7 @@ import javax.net.ssl.X509TrustManager; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import net.sourceforge.tuned.ByteBufferOutputStream; +import net.sourceforge.filebot.util.ByteBufferOutputStream; import org.cyberneko.html.parsers.DOMParser; import org.w3c.dom.Document; diff --git a/test/net/sourceforge/filebot/AllTests.java b/test/net/sourceforge/filebot/AllTests.java index fd9e4931..346e493f 100644 --- a/test/net/sourceforge/filebot/AllTests.java +++ b/test/net/sourceforge/filebot/AllTests.java @@ -1,16 +1,21 @@ - package net.sourceforge.filebot; - -import net.sourceforge.tuned.TunedTestSuite; +import net.sourceforge.filebot.format.ExpressionFormatTest; +import net.sourceforge.filebot.hash.VerificationFormatTest; +import net.sourceforge.filebot.media.ReleaseInfoTest; +import net.sourceforge.filebot.similarity.EpisodeMetricsTest; +import net.sourceforge.filebot.similarity.SimilarityTestSuite; +import net.sourceforge.filebot.subtitle.SubtitleReaderTestSuite; +import net.sourceforge.filebot.ui.rename.MatchModelTest; +import net.sourceforge.filebot.util.UtilTestSuite; +import net.sourceforge.filebot.web.WebTestSuite; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; - @RunWith(Suite.class) -@SuiteClasses( { FileBotTestSuite.class, TunedTestSuite.class }) +@SuiteClasses({ SimilarityTestSuite.class, WebTestSuite.class, ExpressionFormatTest.class, VerificationFormatTest.class, MatchModelTest.class, EpisodeMetricsTest.class, SubtitleReaderTestSuite.class, ReleaseInfoTest.class, UtilTestSuite.class }) public class AllTests { - + } diff --git a/test/net/sourceforge/filebot/FileBotTestSuite.java b/test/net/sourceforge/filebot/FileBotTestSuite.java deleted file mode 100644 index 2a10f40a..00000000 --- a/test/net/sourceforge/filebot/FileBotTestSuite.java +++ /dev/null @@ -1,23 +0,0 @@ - -package net.sourceforge.filebot; - - -import net.sourceforge.filebot.format.ExpressionFormatTest; -import net.sourceforge.filebot.hash.VerificationFormatTest; -import net.sourceforge.filebot.media.ReleaseInfoTest; -import net.sourceforge.filebot.similarity.EpisodeMetricsTest; -import net.sourceforge.filebot.similarity.SimilarityTestSuite; -import net.sourceforge.filebot.subtitle.SubtitleReaderTestSuite; -import net.sourceforge.filebot.ui.rename.MatchModelTest; -import net.sourceforge.filebot.web.WebTestSuite; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - - -@RunWith(Suite.class) -@SuiteClasses( { SimilarityTestSuite.class, WebTestSuite.class, ExpressionFormatTest.class, VerificationFormatTest.class, MatchModelTest.class, EpisodeMetricsTest.class, SubtitleReaderTestSuite.class, ReleaseInfoTest.class }) -public class FileBotTestSuite { - -} diff --git a/test/net/sourceforge/filebot/similarity/NumericSimilarityMetricTest.java b/test/net/sourceforge/filebot/similarity/NumericSimilarityMetricTest.java index e9c18c43..8dda3364 100644 --- a/test/net/sourceforge/filebot/similarity/NumericSimilarityMetricTest.java +++ b/test/net/sourceforge/filebot/similarity/NumericSimilarityMetricTest.java @@ -8,7 +8,7 @@ import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; -import net.sourceforge.tuned.TestUtil; +import net.sourceforge.filebot.util.TestUtil; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/test/net/sourceforge/filebot/util/ByteBufferOutputStreamTest.java b/test/net/sourceforge/filebot/util/ByteBufferOutputStreamTest.java new file mode 100644 index 00000000..84e616a9 --- /dev/null +++ b/test/net/sourceforge/filebot/util/ByteBufferOutputStreamTest.java @@ -0,0 +1,47 @@ + +package net.sourceforge.filebot.util; + + +import static org.junit.Assert.*; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.channels.Channels; +import java.nio.charset.Charset; + +import org.junit.Test; + + +public class ByteBufferOutputStreamTest { + + @Test + public void growBufferAsNeeded() throws Exception { + // initial buffer size of 1, increase size by a factor of 2 if a bigger buffer is needed + ByteBufferOutputStream buffer = new ByteBufferOutputStream(1, 1.0f); + + buffer.write("asdf".getBytes("utf-8")); + + // check content + assertEquals("asdf", Charset.forName("utf-8").decode(buffer.getByteBuffer()).toString()); + + // check capacity + assertEquals(4, buffer.capacity()); + } + + + @Test + public void transferFrom() throws Exception { + InputStream in = new ByteArrayInputStream("asdf".getBytes("utf-8")); + + ByteBufferOutputStream buffer = new ByteBufferOutputStream(4); + + int n = buffer.transferFrom(Channels.newChannel(in)); + + // check number of bytes transfered + assertEquals(4, n); + + // check content + assertEquals("asdf", Charset.forName("utf-8").decode(buffer.getByteBuffer()).toString()); + } + +} diff --git a/test/net/sourceforge/filebot/util/FileUtilitiesTest.java b/test/net/sourceforge/filebot/util/FileUtilitiesTest.java new file mode 100644 index 00000000..c64c673a --- /dev/null +++ b/test/net/sourceforge/filebot/util/FileUtilitiesTest.java @@ -0,0 +1,44 @@ + +package net.sourceforge.filebot.util; + + +import static org.junit.Assert.*; + +import org.junit.Test; + + +public class FileUtilitiesTest { + + @Test + public void hasExtension() { + assertTrue(FileUtilities.hasExtension("abc.txt", "txt")); + assertFalse(FileUtilities.hasExtension(".hidden", "txt")); + } + + + @Test + public void getExtension() { + assertEquals("txt", FileUtilities.getExtension("abc.txt")); + assertEquals("out", FileUtilities.getExtension("a.out")); + assertEquals(null, FileUtilities.getExtension(".hidden")); + assertEquals(null, FileUtilities.getExtension("a.")); + + assertEquals("r00", FileUtilities.getExtension("archive.r00")); + assertEquals(null, FileUtilities.getExtension("archive.r??")); + assertEquals(null, FileUtilities.getExtension("archive.invalid extension")); + } + + + @Test + public void getNameWithoutExtension() { + assertEquals("abc", FileUtilities.getNameWithoutExtension("abc.txt")); + assertEquals("a", FileUtilities.getNameWithoutExtension("a.out")); + assertEquals(".hidden", FileUtilities.getNameWithoutExtension(".hidden")); + assertEquals("a.", FileUtilities.getNameWithoutExtension("a.")); + + assertEquals("archive", FileUtilities.getNameWithoutExtension("archive.r00")); + assertEquals("archive.r??", FileUtilities.getNameWithoutExtension("archive.r??")); + assertEquals("archive.invalid extension", FileUtilities.getNameWithoutExtension("archive.invalid extension")); + } + +} diff --git a/test/net/sourceforge/filebot/util/FilterIteratorTest.java b/test/net/sourceforge/filebot/util/FilterIteratorTest.java new file mode 100644 index 00000000..cc7b5077 --- /dev/null +++ b/test/net/sourceforge/filebot/util/FilterIteratorTest.java @@ -0,0 +1,60 @@ + +package net.sourceforge.filebot.util; + + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + + +public class FilterIteratorTest { + + private List list = new ArrayList(); + + + @Before + public void setUp() { + list.add("first one"); + list.add("2"); + list.add("third space"); + list.add("four square"); + list.add("5"); + list.add("last order"); + } + + + @Test + public void iterateAndRemove() { + Iterator integers = new FilterIterator(list) { + + @Override + protected Integer filter(String sourceValue) { + if (sourceValue.matches("\\d+")) + return Integer.valueOf(sourceValue); + + return null; + } + }; + + assertEquals(Integer.valueOf(2), integers.next()); + integers.remove(); + assertEquals(Integer.valueOf(5), integers.next()); + integers.remove(); + + assertFalse(integers.hasNext()); + + // check if remove() worked + Iterator strings = list.iterator(); + assertEquals("first one", strings.next()); + assertEquals("third space", strings.next()); + assertEquals("four square", strings.next()); + assertEquals("last order", strings.next()); + + assertFalse(strings.hasNext()); + } +} diff --git a/test/net/sourceforge/filebot/util/PreferencesListTest.java b/test/net/sourceforge/filebot/util/PreferencesListTest.java new file mode 100644 index 00000000..1254b83d --- /dev/null +++ b/test/net/sourceforge/filebot/util/PreferencesListTest.java @@ -0,0 +1,113 @@ + +package net.sourceforge.filebot.util; + + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.prefs.Preferences; + +import net.sourceforge.filebot.util.PreferencesMap.SimpleAdapter; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + + +public class PreferencesListTest { + + private static Preferences root; + private static Preferences strings; + private static Preferences numbers; + private static Preferences temp; + + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + root = Preferences.userRoot().node("junit-test"); + + strings = root.node("strings"); + strings.put("0", "Rei"); + strings.put("1", "Firefly"); + strings.put("2", "Roswell"); + strings.put("3", "Angel"); + strings.put("4", "Dead like me"); + strings.put("5", "Babylon"); + + numbers = root.node("numbers"); + numbers.putInt("0", 4); + numbers.putInt("1", 5); + numbers.putInt("2", 2); + + temp = root.node("temp"); + } + + + @AfterClass + public static void tearDownAfterClass() throws Exception { + root.removeNode(); + } + + + @Test + public void get() { + List list = PreferencesList.map(strings); + + assertEquals("Rei", list.get(0)); + assertEquals("Roswell", list.get(2)); + assertEquals("Babylon", list.get(5)); + } + + + @Test + public void add() { + List list = PreferencesList.map(numbers, SimpleAdapter.forClass(Integer.class)); + + list.add(3); + + assertEquals("3", numbers.get("3", null)); + } + + + @Test + public void remove() { + + ArrayList compareValues = new ArrayList(); + + compareValues.add("Gladiator 1"); + compareValues.add("Gladiator 2"); + compareValues.add("Gladiator 3"); + compareValues.add("Gladiator 4"); + compareValues.add("Gladiator 5"); + + List prefs = PreferencesList.map(temp); + prefs.addAll(compareValues); + + for (int index : new int[] { 4, 0, 1 }) { + prefs.remove(index); + compareValues.remove(index); + + assertArrayEquals(compareValues.toArray(), prefs.toArray()); + } + + } + + + @Test + public void setEntry() { + List list = PreferencesList.map(strings); + + list.set(3, "Buffy"); + + assertEquals(strings.get("3", null), "Buffy"); + } + + + @Test + public void toArray() throws Exception { + List list = PreferencesList.map(strings); + + assertArrayEquals(list.subList(0, 3).toArray(), new Object[] { "Rei", "Firefly", "Roswell" }); + } +} diff --git a/test/net/sourceforge/filebot/util/PreferencesMapTest.java b/test/net/sourceforge/filebot/util/PreferencesMapTest.java new file mode 100644 index 00000000..c0edeaf3 --- /dev/null +++ b/test/net/sourceforge/filebot/util/PreferencesMapTest.java @@ -0,0 +1,175 @@ + +package net.sourceforge.filebot.util; + + +import static org.junit.Assert.*; + +import java.awt.Color; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.Map.Entry; +import java.util.prefs.Preferences; + +import net.sourceforge.filebot.util.PreferencesMap.SerializableAdapter; +import net.sourceforge.filebot.util.PreferencesMap.SimpleAdapter; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + + +public class PreferencesMapTest { + + private static Preferences root; + private static Preferences strings; + private static Preferences numbers; + private static Preferences temp; + private static Preferences sequence; + + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + root = Preferences.userRoot().node("junit-test"); + + strings = root.node("strings"); + strings.put("1", "Firefly"); + strings.put("2", "Roswell"); + strings.put("3", "Angel"); + strings.put("4", "Dead like me"); + strings.put("5", "Babylon"); + + numbers = root.node("numbers"); + numbers.putInt("M", 4); + numbers.putInt("A", 5); + numbers.putInt("X", 2); + + sequence = root.node("sequence"); + sequence.putInt("1", 1); + sequence.putInt("2", 2); + sequence.putInt("3", 3); + + temp = root.node("temp"); + } + + + @AfterClass + public static void tearDownAfterClass() throws Exception { + root.removeNode(); + } + + + @Test + public void get() { + Map stringMap = PreferencesMap.map(strings); + + assertEquals("Firefly", stringMap.get("1")); + } + + + @Test + public void put() { + Map stringMap = PreferencesMap.map(temp); + + stringMap.put("key", "snake"); + + assertEquals("snake", temp.get("key", null)); + } + + + @Test + public void remove() throws Exception { + Map map = PreferencesMap.map(numbers, SimpleAdapter.forClass(Integer.class)); + + map.remove("A"); + + assertFalse(Arrays.asList(numbers.keys()).contains("A")); + } + + + @Test + public void clear() throws Exception { + Map map = PreferencesMap.map(temp, SimpleAdapter.forClass(Integer.class)); + + map.put("X", 42); + + map.clear(); + + assertTrue(temp.keys().length == 0); + } + + + @Test + public void containsKey() { + temp.put("name", "kaya"); + + Map map = PreferencesMap.map(temp); + + assertTrue(map.containsKey("name")); + } + + + @Test + public void values() { + + Map map = PreferencesMap.map(sequence, SimpleAdapter.forClass(Integer.class)); + + Collection list = map.values(); + + assertTrue(list.contains(1)); + assertTrue(list.contains(2)); + assertTrue(list.contains(3)); + } + + + @Test + public void containsValue() { + Map map = PreferencesMap.map(strings); + + assertTrue(map.containsValue("Firefly")); + } + + + @Test + public void entrySet() { + Map map = PreferencesMap.map(numbers, SimpleAdapter.forClass(Integer.class)); + + for (Entry entry : map.entrySet()) { + Integer v = entry.getValue(); + entry.setValue(v + 1); + } + + assertEquals(5, numbers.getInt("M", -1)); + } + + + @Test(expected = NumberFormatException.class) + public void adapterException() { + PreferencesMap.map(strings, SimpleAdapter.forClass(Integer.class)).values(); + } + + + @Test + public void containsKeyWithObjectKey() throws Exception { + Map map = PreferencesMap.map(strings); + + assertFalse(map.containsKey(new Object())); + } + + + public void getWithObjectKey() throws Exception { + Map map = PreferencesMap.map(strings); + + assertEquals(null, map.get(new Object())); + } + + + @Test + public void serializableAdapter() { + Map map = PreferencesMap.map(temp, new SerializableAdapter()); + Color color = new Color(0.25f, 0.50f, 1.00f); + + map.put("color", color); + assertEquals(color, map.get("color")); + } +} diff --git a/test/net/sourceforge/filebot/util/TestUtil.java b/test/net/sourceforge/filebot/util/TestUtil.java new file mode 100644 index 00000000..9626648d --- /dev/null +++ b/test/net/sourceforge/filebot/util/TestUtil.java @@ -0,0 +1,41 @@ + +package net.sourceforge.filebot.util; + + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + + +public class TestUtil { + + public static List asParameters(Object... parameters) { + List list = new ArrayList(); + + for (Object parameter : parameters) { + list.add(new Object[] { parameter }); + } + + return list; + } + + + public static List asParameters(Collection parameters) { + return asParameters(parameters.toArray()); + } + + + public static List> rotations(Collection source) { + List> rotations = new ArrayList>(); + + for (int i = 0; i < source.size(); i++) { + List copy = new ArrayList(source); + Collections.rotate(copy, i); + rotations.add(copy); + } + + return rotations; + } + +} diff --git a/test/net/sourceforge/filebot/util/TreeIteratorTest.java b/test/net/sourceforge/filebot/util/TreeIteratorTest.java new file mode 100644 index 00000000..a3f824ce --- /dev/null +++ b/test/net/sourceforge/filebot/util/TreeIteratorTest.java @@ -0,0 +1,76 @@ + +package net.sourceforge.filebot.util; + + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + + +public class TreeIteratorTest { + + private List tree; + + + @Before + public void setUp() throws Exception { + tree = new ArrayList(); + + tree.add("r1"); + + List branch = new ArrayList(); + branch.add("b1"); + branch.add("b2"); + + tree.add(branch); + + tree.add("r2"); + + List treetop = new ArrayList(); + treetop.add("t1"); + treetop.add("t2"); + treetop.add("t3"); + + List trunk = new ArrayList(); + trunk.add(treetop); + + tree.add(trunk); + } + + + @Test + public void iterate() { + TreeIterator treeIterator = new TreeIterator(tree) { + + @SuppressWarnings("unchecked") + @Override + protected Iterator children(Object node) { + if (node instanceof Iterable) + return ((Iterable) node).iterator(); + + return null; + } + + }; + + // check leafs (String) and nodes (Iterable) + assertTrue(treeIterator.next() instanceof Iterable); // root + assertEquals("r1", treeIterator.next()); + assertTrue(treeIterator.next() instanceof Iterable); // branch + assertEquals("b1", treeIterator.next()); + assertEquals("b2", treeIterator.next()); + assertEquals("r2", treeIterator.next()); + assertTrue(treeIterator.next() instanceof Iterable); // trunk + assertTrue(treeIterator.next() instanceof Iterable); // treetop + assertEquals("t1", treeIterator.next()); + assertEquals("t2", treeIterator.next()); + assertEquals("t3", treeIterator.next()); + + assertFalse(treeIterator.hasNext()); + } +} diff --git a/test/net/sourceforge/filebot/util/UtilTestSuite.java b/test/net/sourceforge/filebot/util/UtilTestSuite.java new file mode 100644 index 00000000..3ff9171a --- /dev/null +++ b/test/net/sourceforge/filebot/util/UtilTestSuite.java @@ -0,0 +1,14 @@ + +package net.sourceforge.filebot.util; + + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + + +@RunWith(Suite.class) +@SuiteClasses( { FileUtilitiesTest.class, ByteBufferOutputStreamTest.class, PreferencesMapTest.class, PreferencesListTest.class, TreeIteratorTest.class, FilterIteratorTest.class }) +public class UtilTestSuite { + +}