From 908057b133f31667d8218d00962a341b2abc48d9 Mon Sep 17 00:00:00 2001 From: Herr Ritschwumm Date: Sat, 18 Jan 2014 02:42:19 +0100 Subject: [PATCH] updated libraries, cleanup build, added FAL license, default to wikimedia commons, code cleanups --- build.sbt | 15 ++- project/build.properties | 2 +- project/plugins.sbt | 10 +- src/main/doc/changes.txt | 7 ++ src/main/resources/licenses.txt | 3 + src/main/resources/messages_de.properties | 5 +- src/main/resources/wikis.txt | 16 +-- src/main/scala/commonist/Commonist.scala | 17 ++- src/main/scala/commonist/Constants.scala | 1 - src/main/scala/commonist/Parser.scala | 13 +-- .../commonist/task/ChangeDirectoryTask.scala | 6 +- .../commonist/task/UploadFilesTask.scala | 37 ++++--- .../task/upload/UploadTemplates.scala | 8 +- .../scala/commonist/thumb/FileCache.scala | 18 ++-- .../scala/commonist/thumb/Thumbnails.scala | 100 ++++++++---------- src/main/scala/commonist/ui/CommonUI.scala | 16 +-- src/main/scala/commonist/ui/DirectoryUI.scala | 2 +- src/main/scala/commonist/ui/FileNode.scala | 2 +- .../scala/commonist/ui/FullImageWindow.scala | 4 +- src/main/scala/commonist/ui/ImageListUI.scala | 37 ++++--- src/main/scala/commonist/ui/ImageUI.scala | 24 +---- .../commonist/ui/ScrollablePicture.scala | 6 +- src/main/scala/commonist/util/EXIF.scala | 6 +- src/main/scala/commonist/util/Loader.scala | 4 +- src/main/scala/commonist/util/Messages.scala | 6 +- src/main/scala/commonist/util/Settings.scala | 4 +- .../commonist/util/TextComponentUndo.scala | 15 +-- src/main/scala/commonist/util/TextUtil2.scala | 8 +- 28 files changed, 199 insertions(+), 193 deletions(-) diff --git a/build.sbt b/build.sbt index ee36192..613ea3f 100644 --- a/build.sbt +++ b/build.sbt @@ -2,14 +2,13 @@ name := "commonist" organization := "de.djini" -version := "0.8.0" +version := "0.9.0" scalaVersion := "2.10.3" libraryDependencies ++= Seq( - "de.djini" %% "scutil" % "0.34.0" % "compile", - "de.djini" %% "scjson" % "0.37.0" % "compile", - "de.djini" %% "scmw" % "0.33.0" % "compile", + "de.djini" %% "scutil" % "0.40.0" % "compile", + "de.djini" %% "scmw" % "0.40.0" % "compile", "org.apache.sanselan" % "sanselan" % "0.97-incubator" % "compile", "org.simplericity.macify" % "macify" % "1.6" % "compile" ) @@ -17,7 +16,7 @@ libraryDependencies ++= Seq( scalacOptions ++= Seq( "-deprecation", "-unchecked", - // "-language:implicitConversions", + "-language:implicitConversions", // "-language:existentials", // "-language:higherKinds", // "-language:reflectiveCalls", @@ -58,7 +57,7 @@ osxappSettings osxappBundleName := "commonist" -osxappBundleIcons := file("src/main/osxapp/commonist.icns") +osxappBundleIcons := baseDirectory.value / "src/main/osxapp/commonist.icns" osxappVm := OracleJava7() @@ -82,13 +81,13 @@ webstartGenConfig := Some(GenConfig( )) webstartKeyConfig := Some(KeyConfig( - keyStore = file("etc/keyStore"), + keyStore = baseDirectory.value / "etc/keyStore", storePass = "0xDEADBEEF", alias = "signFiles", keyPass = "0xDEADBEEF" )) -webstartManifest := Some(file("etc/manifest.mf")) +webstartManifest := Some(baseDirectory.value / "etc/manifest.mf") webstartJnlpConfigs := Seq(JnlpConfig( fileName = "commonist.jnlp", diff --git a/project/build.properties b/project/build.properties index 0974fce..37b489c 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.0 +sbt.version=0.13.1 diff --git a/project/plugins.sbt b/project/plugins.sbt index c949077..835b3e4 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,9 +1,9 @@ -addSbtPlugin("de.djini" % "xsbt-webstart" % "0.13.0") +addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.3.0") -addSbtPlugin("de.djini" % "xsbt-scriptstart" % "0.13.0") +addSbtPlugin("de.djini" % "xsbt-webstart" % "0.15.0") -addSbtPlugin("de.djini" % "xsbt-osxapp" % "0.8.0") +addSbtPlugin("de.djini" % "xsbt-scriptstart" % "0.15.0") -addSbtPlugin("de.djini" % "xsbt-zipper" % "0.6.0") +addSbtPlugin("de.djini" % "xsbt-osxapp" % "0.11.0") -addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.2.5") +addSbtPlugin("de.djini" % "xsbt-zipper" % "0.7.0") diff --git a/src/main/doc/changes.txt b/src/main/doc/changes.txt index 2c41c2c..7fbf983 100644 --- a/src/main/doc/changes.txt +++ b/src/main/doc/changes.txt @@ -1,3 +1,10 @@ +0.9.0 18jan14 + change added FAL license + change mediawiki was a stupid default for the wiki, + using commons again. + change updated libraries. + change build with sbt 0.13.1 + 0.8.0 24nov13 change changed all wikis to use https change use scmw-0.33.0 to use new httpclient 4.3.1 diff --git a/src/main/resources/licenses.txt b/src/main/resources/licenses.txt index 3438854..4806d1b 100644 --- a/src/main/resources/licenses.txt +++ b/src/main/resources/licenses.txt @@ -49,6 +49,9 @@ # Non-free licenses: {{Copyright by Wikimedia}} Wikimedia logos +# Other copyleft licenses: +{{FAL}} Copyleft: This work of art is free; you can redistribute it and/or modify it according to terms of the Free Art License. + ## OLD #{{self2|GFDL|cc-by-sa-2.5,2.0,1.0}} Own work, copyleft: Multi-license with GFDL and Creative Commons CC-BY-SA-2.5 and older versions (2.0 and 1.0) #{{self2|GFDL|cc-by-2.5}} Own work, attribution required (Multi-license with GFDL and Creative Commons CC-BY 2.5) diff --git a/src/main/resources/messages_de.properties b/src/main/resources/messages_de.properties index 383cc33..03873cd 100644 --- a/src/main/resources/messages_de.properties +++ b/src/main/resources/messages_de.properties @@ -61,8 +61,8 @@ status.gallery.error=konnte Galerie nicht \u00e4ndern ({0}) # callback queries query.upload.title=Problem beim Upload -query.upload.body=Es geht um die Datei {0}:\n{1}\nDennoch hochladen und gegebenenfalls überschreiben? -query.upload.ignoreFileexists.message=Datei ist bereits vorhanden und würde überschrieben. +query.upload.body=Es geht um die Datei {0}:\n{1}\nDennoch hochladen und gegebenenfalls \u00fcberschreiben? +query.upload.ignoreFileexists.message=Datei ist bereits vorhanden und w\u00fcrde \u00fcberschrieben. query.upload.ignoreFilewasdeleted.message=Datei wurde schon einmal gel\u00f6scht. query.upload.ignoreDuplicate.message=Datei ist ein Duplikat von {1}. query.upload.ignoreDuplicateArchive.message=Datei ist ein Archiv-Duplikat von {1}. @@ -70,3 +70,4 @@ query.upload.ignoreDuplicateArchive.message=Datei ist ein Archiv-Duplikat von {1 # action buttons upload.upload=Hochladen upload.abort=Abbrechen + diff --git a/src/main/resources/wikis.txt b/src/main/resources/wikis.txt index d6a19e9..bcc33eb 100644 --- a/src/main/resources/wikis.txt +++ b/src/main/resources/wikis.txt @@ -1,11 +1,3 @@ -# other -# kamelopedia _ http://kamelopedia.mormo.org/api.php -mediawiki _ https://www.mediawiki.org/w/api.php - -# wikia -wikia foto https://foto.wikia.com/api.php -wikia uncyclopedia https://uncyclopedia.wikia.com/api.php - # wikimedia wikimedia commons https://commons.wikimedia.org/w/api.php wikimedia meta https://meta.wikimedia.org/w/api.php @@ -101,3 +93,11 @@ wiktionary nl https://nl.wiktionary.org/w/api.php wiktionary pl https://pl.wiktionary.org/w/api.php wiktionary pt https://pt.wiktionary.org/w/api.php wiktionary sv https://sv.wiktionary.org/w/api.php + +# other +# kamelopedia _ http://kamelopedia.mormo.org/api.php +mediawiki _ https://www.mediawiki.org/w/api.php + +# wikia +wikia foto https://foto.wikia.com/api.php +wikia uncyclopedia https://uncyclopedia.wikia.com/api.php diff --git a/src/main/scala/commonist/Commonist.scala b/src/main/scala/commonist/Commonist.scala index 843cec6..0d499e5 100644 --- a/src/main/scala/commonist/Commonist.scala +++ b/src/main/scala/commonist/Commonist.scala @@ -10,7 +10,7 @@ import bsh.EvalError import org.simplericity.macify.eawt._ -import scutil.Implicits._ +import scutil.implicits._ import scutil.platform._ import scutil.io.Files._ import scutil.gui.SwingApp @@ -39,18 +39,18 @@ object Commonist extends SwingApp with Logging { private val etcDir = PWD / "etc" private val resourcesDir = PWD / "src" / "main" / "resources" private val resourcePrefix = "/" - INFO("settings directory: " + settingsDir) - INFO("etc directory: " + etcDir) - INFO("resources directory: " + resourcesDir) + INFO("settings directory", settingsDir) + INFO("etc directory", etcDir) + INFO("resources directory", resourcesDir) settingsDir.mkdirs() require(settingsDir.exists, "settings directory cannot be created") private val loader = new Loader(settingsDir, etcDir, resourcesDir, resourcePrefix) val programIcon = null - val programHeading = "The Commonist " + Constants.VERSION + val programHeading = s"The Commonist ${commonist.BuildInfo.version}" private val userLanguage = SystemProperties.user.language - INFO("using user language: " + userLanguage) + INFO("using user language", userLanguage) loadMessages(userLanguage) private val licenses = loadLicenses() @@ -93,8 +93,7 @@ object Commonist extends SwingApp with Logging { doQuit() } } - "/commonist-128.png" |> getClass.getResource |> ImageIO.read |> - macifyApplication.setApplicationIconImage + macifyApplication setApplicationIconImage ("/commonist-128.png" |> getClass.getResource |> ImageIO.read) macifyApplication.removeAboutMenuItem() macifyApplication.removePreferencesMenuItem() @@ -178,7 +177,7 @@ object Commonist extends SwingApp with Logging { /** load language file for the language or en if not successful and returns the used language */ private def loadMessages(language:String) { val defaultURL = loader resourceURL "messages_default.properties" getOrError "cannot load messages_default.properties" - val userLangURL = loader resourceURL ("messages_" + language + ".properties") + val userLangURL = loader resourceURL (s"messages_${language}.properties") Messages init (defaultURL, userLangURL) } diff --git a/src/main/scala/commonist/Constants.scala b/src/main/scala/commonist/Constants.scala index 02139e7..657fe45 100644 --- a/src/main/scala/commonist/Constants.scala +++ b/src/main/scala/commonist/Constants.scala @@ -4,7 +4,6 @@ import javax.swing.BorderFactory /** constants used throughout the application */ object Constants { - val VERSION = BuildInfo.version val ENABLE_API_WRITE = true // if false the API is dry-running val ENABLE_GALLERY = true diff --git a/src/main/scala/commonist/Parser.scala b/src/main/scala/commonist/Parser.scala index 5005347..14abddc 100644 --- a/src/main/scala/commonist/Parser.scala +++ b/src/main/scala/commonist/Parser.scala @@ -4,7 +4,8 @@ import java.io._ import java.net._ import java.util.regex._ -import scutil.Implicits._ +import scutil.implicits._ +import scutil.io.Charsets.utf_8 import scutil.log._ import scmw._ @@ -71,11 +72,11 @@ object Parser extends Logging { private def parseURL[T](url:URL)(parseLine:String=>Iterable[T]):Seq[T] = slurpLines(url) - .map { _.trim } - .filter { _.nonEmpty } - .filter { !_.startsWith("#") } - .flatMap { parseLine } + .map { _.trim } + .filter { _.nonEmpty } + .filter { !_.startsWith("#") } + .flatMap { parseLine } private def slurpLines(url:URL):Seq[String] = - new BufferedReader(new InputStreamReader(url.openStream, "UTF-8")) use { _.readLines() } + (url withReader utf_8) { _.readLines() } } diff --git a/src/main/scala/commonist/task/ChangeDirectoryTask.scala b/src/main/scala/commonist/task/ChangeDirectoryTask.scala index dbe18b5..927a926 100644 --- a/src/main/scala/commonist/task/ChangeDirectoryTask.scala +++ b/src/main/scala/commonist/task/ChangeDirectoryTask.scala @@ -3,7 +3,7 @@ package commonist.task import java.io.File import javax.swing.Icon -import scutil.Implicits._ +import scutil.implicits._ import scutil.log._ import commonist._ @@ -26,13 +26,13 @@ final class ChangeDirectoryTask(mainWindow:MainWindow, imageListUI:ImageListUI, // TODO handle null val listed = directory .childrenWhere { file:File => file.isFile && !file.isHidden } - .getOrElse { WARN("directory does not exist: " + directory); return } + .getOrElse { WARN("directory does not exist", directory); return } // TODO duplicate code val sorted = listed sortBy { _.getPath } val (readable,unreadable) = sorted partition { _.canRead } - unreadable foreach { it => WARN("cannot read: " + it) } + unreadable foreach { it => WARN("cannot read", it) } val max = readable.length var cur = 0 diff --git a/src/main/scala/commonist/task/UploadFilesTask.scala b/src/main/scala/commonist/task/UploadFilesTask.scala index 91bacfe..b5d5095 100644 --- a/src/main/scala/commonist/task/UploadFilesTask.scala +++ b/src/main/scala/commonist/task/UploadFilesTask.scala @@ -7,7 +7,7 @@ import javax.swing.JOptionPane import scala.collection.JavaConverters._ -import scutil.Implicits._ +import scutil.implicits._ import scutil.io.Charsets import scutil.gui.SwingUtil._ import scutil.log._ @@ -90,16 +90,16 @@ final class UploadFilesTask( val loginResult = api login (commonData.user.trim, commonData.password) loginResult match { case LoginSuccess(userName) => - INFO("login successful: " + userName) + INFO("login successful", userName) statusUILater halt ("status.login.successful", wikiName) true case LoginFailure(code) => - INFO("login failed: " + code) + INFO("login failed", code) // TODO more detail statusUILater halt ("status.login.wrongpw", wikiName) false case LoginError(code) => - INFO("login error: " + code) + INFO("login error", code) statusUILater halt ("status.login.error", wikiName, code) false } @@ -158,25 +158,25 @@ final class UploadFilesTask( val uploaded = api upload (name, "", text, watch, file, callback) uploaded match { case UploadSuccess(fileName, pageTitle) => - INFO("upload successful: " + fileName + " to " + pageTitle) + INFO("upload successful", fileName, pageTitle) statusUILater halt ("status.upload.successful", fileName, pageTitle) imageListUILater uploadFinished (file, true) upload copy (name=fileName, title=pageTitle) case UploadAborted(warnings) => - ERROR("upload aborted: " + fileName) + ERROR("upload aborted", fileName) statusUILater halt ("status.upload.error", fileName, "aborted") imageListUILater uploadFinished (file, false) // TODO just remove it from the list? // TODO more detail - upload copy (error="aborted: " + renderWarnings(warnings)) + upload copy (error=s"aborted: ${renderWarnings(warnings)}") case UploadFailure(code) => // TODO more detail - ERROR("upload failed: " + fileName + " because " + code) + ERROR("upload failed", fileName, code) statusUILater halt ("status.upload.error", fileName, code) imageListUILater uploadFinished (file, false) upload copy (error=code) case UploadError(code) => - ERROR("upload error: " + fileName + " because " + code) + ERROR("upload error", fileName, code) statusUILater halt ("status.upload.error", fileName, code) imageListUILater uploadFinished (file, false) upload copy (error=code) @@ -199,6 +199,9 @@ final class UploadFilesTask( private def renderFile(name:String):String = "[[:" + (Namespace file name) + "]]" + + private def renderLink(s:String):String = + "[[" + s + "]]" /* statusUILater halt ("status.gallery.error", e.getMessage) @@ -216,33 +219,33 @@ final class UploadFilesTask( sucesses.asJava, failures.asJava ) - val summary = uploadTemplates gallerySummary (Constants.VERSION, failures.size) + val summary = uploadTemplates gallerySummary (commonist.BuildInfo.version, failures.size) val text = uploadTemplates galleryDescription (common, batch) // backup gallery text val backup = settingsDir / "gallery.txt" - INFO("writing gallery to: " + backup) + INFO("writing gallery", backup) backup writeString (Charsets.utf_8, text) - statusUILater indeterminate ("status.gallery.loading", "[[" + title + "]]") + statusUILater indeterminate ("status.gallery.loading", renderLink(title)) val editResult = api edit (title, summary, None, { oldText => - statusUILater indeterminate ("status.gallery.storing", "[[" + title + "]]") + statusUILater indeterminate ("status.gallery.storing", renderLink(title)) val newText = text + "\n\n" + (TextUtil2 trimLF oldText) Some(newText) }) editResult match { case EditSuccess(pageTitle) => - statusUILater halt ("status.gallery.updated", "[[" + title + "]]") + statusUILater halt ("status.gallery.updated", renderLink(title)) case EditAborted => // will not happen case EditFailure(code) => // TODO more detail - statusUILater halt ("status.gallery.error", code + " in [[" + title + "]]") + statusUILater halt ("status.gallery.error", code + " in " + renderLink(title)) case EditError(code) => - statusUILater halt ("status.gallery.error", code + " in [[" + title + "]]") + statusUILater halt ("status.gallery.error", code + " in " + renderLink(title)) } } - + /* statusUILater halt ("status.logout.error", wikiName, e.getMessage) if (!success) { statusUILater halt ("status.logout.failed", wikiName); return } diff --git a/src/main/scala/commonist/task/upload/UploadTemplates.scala b/src/main/scala/commonist/task/upload/UploadTemplates.scala index fbfb0dc..10eee95 100644 --- a/src/main/scala/commonist/task/upload/UploadTemplates.scala +++ b/src/main/scala/commonist/task/upload/UploadTemplates.scala @@ -6,7 +6,7 @@ import java.net._ import net.psammead.minibpp.Compiler import bsh.Interpreter -import scutil.Implicits._ +import scutil.implicits._ import scutil.log._ import commonist.data._ @@ -16,7 +16,7 @@ import commonist.util._ final class UploadTemplates(loader:Loader, wiki:WikiData) extends Logging { /** edit summary for writing a gallery */ def gallerySummary(version:String, failureCount:Int):String = - "commonist " + version + ((failureCount != 0) cata ("", ", " + failureCount + " errors")) + "commonist " + version + ((failureCount != 0) cata ("", s", ${failureCount} errors")) /** compiles into wikitext */ def galleryDescription(common:Common, batch:Batch):String = @@ -33,11 +33,11 @@ final class UploadTemplates(loader:Loader, wiki:WikiData) extends Logging { )) private def template(typ:String, data:Map[String,AnyRef]):String = { - val specific = typ + "_" + wiki.family + (wiki.site map { "_" + _ } getOrElse "") + ".bpp" + val specific = typ + "_" + wiki.family + (wiki.site cata ("", "_" + _)) + ".bpp" val generic = typ + "_default.bpp" val url = (loader resourceURL specific) orElse (loader resourceURL generic) getOrError - ("neither specific template: " + specific + " nor generic template: " + generic + " could be found") + (s"neither specific template: ${specific} nor generic template: ${generic} could be found") try { compile(url, data) |> TextUtil2.restrictEmptyLines |> TextUtil2.trimLF } diff --git a/src/main/scala/commonist/thumb/FileCache.scala b/src/main/scala/commonist/thumb/FileCache.scala index 427b3f2..d83e06f 100644 --- a/src/main/scala/commonist/thumb/FileCache.scala +++ b/src/main/scala/commonist/thumb/FileCache.scala @@ -5,7 +5,7 @@ import java.lang.{ Math => JMath } import scala.collection.immutable.Queue -import scutil.Implicits._ +import scutil.implicits._ import scutil.io.Charsets._ import scutil.log._ @@ -38,8 +38,8 @@ final class FileCache(list:File, directory:File, cachedFiles:Int) extends Loggin // insert a new entry val cached = cacheFile() - INFO("caching original: " + original) - INFO("cached thumbnail: " + cached) + INFO("caching original", original) + INFO("cached thumbnail", cached) entryQueue = entryQueue enqueue original entryMap = entryMap + (original -> cached) cached @@ -48,11 +48,11 @@ final class FileCache(list:File, directory:File, cachedFiles:Int) extends Loggin /** remove an entry */ def remove(original:File) { val cached = entryMap get original - DEBUG("removing original: " + original) + DEBUG("removing original", original) entryQueue = entryQueue filterNot { _ ==== original } entryMap = entryMap - original cached filter { _.exists } foreach { cached => - INFO("deleting cached: " + cached) + INFO("deleting cached", cached) cached.delete() } } @@ -103,9 +103,9 @@ final class FileCache(list:File, directory:File, cachedFiles:Int) extends Loggin } { entryQueue = newQueue entryMap = newMap - DEBUG("flushing original: " + oldOriginal) + DEBUG("flushing original", oldOriginal) if (oldCached.exists) { - INFO("deleting cached: " + oldCached) + INFO("deleting cached", oldCached) oldCached.delete() } } @@ -119,7 +119,7 @@ final class FileCache(list:File, directory:File, cachedFiles:Int) extends Loggin private def cleanup() { // remove stale entries from the entryList and entryMap entryQueue filterNot { _.exists } foreach { original => - WARN("original disappeared: " + original) + WARN("original disappeared", original) entryQueue = entryQueue filterNot { _ ==== original } entryMap = entryMap - original } @@ -128,7 +128,7 @@ final class FileCache(list:File, directory:File, cachedFiles:Int) extends Loggin val entries = entryMap.values.toSet val listed = directory.listFiles // TODO handle null listed filterNot entries.contains foreach { cached => - INFO("deleting cached: " + cached) + INFO("deleting cached", cached) cached.delete() } } diff --git a/src/main/scala/commonist/thumb/Thumbnails.scala b/src/main/scala/commonist/thumb/Thumbnails.scala index d44d03c..23cb4dd 100644 --- a/src/main/scala/commonist/thumb/Thumbnails.scala +++ b/src/main/scala/commonist/thumb/Thumbnails.scala @@ -8,6 +8,8 @@ import java.awt.image._ import javax.swing._ import javax.imageio._ +import scutil.lang._ +import scutil.implicits._ import scutil.log._ import commonist.Constants @@ -33,30 +35,26 @@ final class Thumbnails(cache:FileCache) extends Logging { cachedThumbnail(file) map { new ImageIcon(_) } } catch { case e:Exception => - INFO("cannot create thumbnail from " + file, e) + INFO("cannot create thumbnail", file, e) None } /** make a thumbnail or return a cached version */ private def cachedThumbnail(file:File):Option[Image] = - // TODO give the cache a loader instead of talking to it here - + // BETTER give the cache a loader instead of talking to it here // try to get cached thumb - (cache get file) map { ImageIO read _ } orElse { - // read original and make thumb - val thumb = readSubsampled(file) map makeThumbnail - - thumb foreach { thumb => + (cache get file) map { ImageIO read _ } orElse + // read original and make thumb + readSubsampled(file) map makeThumbnail doto { + _ foreach { thumb => // cache thumb val thumbFile2 = cache put file val success = ImageIO write (thumb, "jpg", thumbFile2) if (!success) { - WARN("could not create thumbnail: " + thumbFile2) + WARN("could not create thumbnail", thumbFile2) cache remove file } } - - thumb } /** makes a thumbnail from an image */ @@ -65,7 +63,6 @@ final class Thumbnails(cache:FileCache) extends Logging { if (scale >= 1.0) return image // TODO check more image types - // seen: TYPE_BYTE_GRAY and TYPE_BYTE_INDEXED, // TYPE_CUSTOM needs conversion or throws an ImagingOpException at transformation time // TYPE_3BYTE_BGR works without conversion @@ -74,21 +71,18 @@ final class Thumbnails(cache:FileCache) extends Logging { // TYPE_BYTE_INDEXED works, but inverts color if converted to TYPE_3BYTE_BGR // normalize image type - val imageType = image.getType + val normalizeTypes = Set(BufferedImage.TYPE_3BYTE_BGR, BufferedImage.TYPE_BYTE_INDEXED) val image2 = - if (imageType != BufferedImage.TYPE_3BYTE_BGR - && imageType != BufferedImage.TYPE_BYTE_INDEXED) { - // if (imageType == BufferedImage.TYPE_CUSTOM - // || imageType == BufferedImage.TYPE_BYTE_GRAY - // || imageType == BufferedImage.TYPE_INT_RGB) { + if (normalizeTypes contains image.getType) { val normalized = new BufferedImage( image.getWidth, image.getHeight, BufferedImage.TYPE_3BYTE_BGR) - val g = normalized.getGraphics - g drawImage (image, 0, 0, null) - g.dispose() - normalized + normalized doto { + _.getGraphics use { g => + g drawImage (image, 0, 0, null) + } + } } else { image @@ -111,39 +105,37 @@ final class Thumbnails(cache:FileCache) extends Logging { /** scales down when the image is too big */ private def readSubsampled(input:File):Option[BufferedImage] = { - // ImageIO.read(file) - - val stream = ImageIO.createImageInputStream(input) - if (stream == null) throw new IOException("cannot create ImageInputStream for file: " + input) - - val it = ImageIO getImageReaders stream - if (!it.hasNext) { - WARN("could not read original: " + input) - return None // throw new IOException("cannot create ImageReader for file: " + input) + val stream = ImageIO createImageInputStream input + if (stream == null) { + ERROR(s"cannot create ImageInputStream for file", input) + return None } + stream use { stream => + val it = ImageIO getImageReaders stream + if (!it.hasNext) { + ERROR("cannot get ImageReader for file", input) + return None + } + + it.next use { reader => + reader setInput (stream, true, true) + + val param = reader.getDefaultReadParam + + val imageIndex = 0 - val reader = it.next - reader setInput (stream, true, true) - - val param = reader.getDefaultReadParam - - val imageIndex = 0 - - val sizeX = reader getWidth imageIndex - val sizeY = reader getHeight imageIndex - val size = sizeX min sizeY - val scale = size / maxSize - val sampling = JInteger highestOneBit (scale * 100 / Constants.THUMBNAIL_SCALE_HEADROOM) -// System.err.println("#### scale=" + scale + "\t=> sampling=" + sampling) - - // TODO could scale at load time! - if (sampling > 1) param setSourceSubsampling (sampling, sampling, 0, 0) - val image = reader read (imageIndex, param) - - // TODO try/catch - reader.dispose() - stream.close() - - Some(image) + val sizeX = reader getWidth imageIndex + val sizeY = reader getHeight imageIndex + val size = sizeX min sizeY + val scale = size / maxSize + val sampling = JInteger highestOneBit (scale * 100 / Constants.THUMBNAIL_SCALE_HEADROOM) + + // BETTER could scale at load time! + if (sampling > 1) param setSourceSubsampling (sampling, sampling, 0, 0) + val image = reader read (imageIndex, param) + + Some(image) + } + } } } diff --git a/src/main/scala/commonist/ui/CommonUI.scala b/src/main/scala/commonist/ui/CommonUI.scala index bc67dfe..525e6e7 100644 --- a/src/main/scala/commonist/ui/CommonUI.scala +++ b/src/main/scala/commonist/ui/CommonUI.scala @@ -4,7 +4,7 @@ import java.awt.{ List => AwtList, _ } import java.awt.event._ import javax.swing._ -import scutil.Implicits._ +import scutil.implicits._ import scutil.gui.GridBagDSL._ import scutil.gui.CasterInstances._ @@ -49,9 +49,11 @@ final class CommonUI(wikiList:Seq[WikiData], licenseList:Seq[LicenseData]) exten private val permissionEditor = new JTextField(Constants.INPUT_FIELD_WIDTH) with TextComponentUndo private val categoriesEditor = new JTextField(Constants.INPUT_FIELD_WIDTH) with TextComponentUndo private val licenseEditor = new JComboBox(licenseList.toArray[Object]) { - override def getPreferredSize():Dimension = new Dimension( - 10, - super.getPreferredSize.height) + override def getPreferredSize():Dimension = + new Dimension( + 10, + super.getPreferredSize.height + ) } // NOTE licenseEditor#SelectedItem is String|LicenseData @@ -75,7 +77,7 @@ final class CommonUI(wikiList:Seq[WikiData], licenseList:Seq[LicenseData]) exten licenseEditor.getSelectedItem match { case x:LicenseData => x.description case x:String => x - case x => sys error ("unexpected license type: " + x) + case x => sys error s"unexpected license type: ${x}" } licenseEditor setToolTipText text } @@ -147,7 +149,7 @@ final class CommonUI(wikiList:Seq[WikiData], licenseList:Seq[LicenseData]) exten licenseEditor.getSelectedItem match { case x:String => LicenseData(x, "") case x:LicenseData => x - case x => sys error ("unexpected license type: " + x) + case x => sys error s"unexpected license type: ${x}" }, categoriesEditor.getText ) @@ -195,7 +197,7 @@ final class CommonUI(wikiList:Seq[WikiData], licenseList:Seq[LicenseData]) exten licenseEditor.getSelectedItem match { case x:LicenseData => x.template case x:String => x - case x => sys error ("unexpected license type: " + x) + case x => sys error s"unexpected license type: ${x}" } settings set ("licenseEditor.SelectedItem", licenseSel) } diff --git a/src/main/scala/commonist/ui/DirectoryUI.scala b/src/main/scala/commonist/ui/DirectoryUI.scala index ef05abe..aeb4dc6 100644 --- a/src/main/scala/commonist/ui/DirectoryUI.scala +++ b/src/main/scala/commonist/ui/DirectoryUI.scala @@ -6,7 +6,7 @@ import javax.swing._ import javax.swing.event._ import javax.swing.tree._ -import scutil.Implicits._ +import scutil.implicits._ import scutil.io.Files._ import scutil.platform.SystemProperties import scutil.gui.CasterInstances._ diff --git a/src/main/scala/commonist/ui/FileNode.scala b/src/main/scala/commonist/ui/FileNode.scala index 2085a9f..c0c40c6 100644 --- a/src/main/scala/commonist/ui/FileNode.scala +++ b/src/main/scala/commonist/ui/FileNode.scala @@ -7,7 +7,7 @@ import javax.swing.tree.TreePath import scala.collection.JavaConverters._ -import scutil.Implicits._ +import scutil.implicits._ /** a TreeNode for a File in the DirectoryTree */ final class FileNode(val file:File) extends DefaultMutableTreeNode { diff --git a/src/main/scala/commonist/ui/FullImageWindow.scala b/src/main/scala/commonist/ui/FullImageWindow.scala index 6b76e46..321ea94 100644 --- a/src/main/scala/commonist/ui/FullImageWindow.scala +++ b/src/main/scala/commonist/ui/FullImageWindow.scala @@ -23,11 +23,11 @@ object FullImageWindow extends Logging { } } else { - WARN("cannot load image: " + file) + WARN("cannot load image", file) } } catch { case e:IOException => - WARN("cannot load image: " + file, e) + WARN("cannot load image", file, e) } } } diff --git a/src/main/scala/commonist/ui/ImageListUI.scala b/src/main/scala/commonist/ui/ImageListUI.scala index ae6444c..9322c5e 100644 --- a/src/main/scala/commonist/ui/ImageListUI.scala +++ b/src/main/scala/commonist/ui/ImageListUI.scala @@ -24,8 +24,13 @@ final class ImageListUI(programHeading:String, programIcon:Image) extends JPanel private val listPanel = new ListPanel() listPanel setLayout new BoxLayout(listPanel, BoxLayout.Y_AXIS) - private val scroll = new JScrollPane(listPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER) - scroll setBorder (BorderFactory createEmptyBorder (0,0,0,0)) //### scrollBorder? + private val scroll = + new JScrollPane( + listPanel, + ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, + ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER + ) + scroll setBorder (BorderFactory createEmptyBorder (0,0,0,0)) //var bar = scroll.getVerticalScrollBar @@ -76,7 +81,7 @@ final class ImageListUI(programHeading:String, programIcon:Image) extends JPanel def add(file:File, icon:Option[Icon], thumbnailMaxSize:Int) { val imageUI = new ImageUI(file, icon, thumbnailMaxSize, programHeading, programIcon, new ImageUICallback { - def updateSelectStatus() { outer.updateSelectStatus() } + def updateSelectStatus() { outer.updateSelectStatus() } }) imageUIs += imageUI @@ -90,19 +95,25 @@ final class ImageListUI(programHeading:String, programIcon:Image) extends JPanel val allBytes = (allFiles map { _.length }).foldLeft (0L)(_+_) val selectedBytes = (selectedFiles map { _.length }).foldLeft (0L)(_+_) - selectStatus.setText(Messages message ("imageList.selected", - int2Integer(selectedFiles.size), - int2Integer(allFiles.size), - TextUtil2 human selectedBytes, - TextUtil2 human allBytes - )) + selectStatus setText ( + Messages message ( + "imageList.selected", + int2Integer(selectedFiles.size), + int2Integer(allFiles.size), + TextUtil2 human selectedBytes, + TextUtil2 human allBytes + ) + ) } - def getData:ImageListData = new ImageListData(imageUIs.toList map { _.getData }) + def getData:ImageListData = + ImageListData(imageUIs.toList map { _.getData }) /** set the upload state for the ImageUI representing the given file */ def uploadFinished(file:File, success:Boolean) { - imageUIs filter { _.getData.file == file } foreach { _ setUploadSuccessful Some(success) } + imageUIs + .filter { _.getData.file == file } + .foreach { _ setUploadSuccessful Some(success) } } //------------------------------------------------------------------------------ @@ -122,7 +133,9 @@ final class ImageListUI(programHeading:String, programIcon:Image) extends JPanel /** checks for the upload checkbox in all failed images, unchecks it for the rest */ private def selectFailed() { - imageUIs foreach { it => it setUploadSelected (it.getUploadSuccessful == Some(false)) } + imageUIs foreach { it => + it setUploadSelected (it.getUploadSuccessful == Some(false)) + } updateSelectStatus() } diff --git a/src/main/scala/commonist/ui/ImageUI.scala b/src/main/scala/commonist/ui/ImageUI.scala index f733617..8b5e3aa 100644 --- a/src/main/scala/commonist/ui/ImageUI.scala +++ b/src/main/scala/commonist/ui/ImageUI.scala @@ -6,7 +6,7 @@ import java.awt.event._ import javax.swing._ import scutil.lang._ -import scutil.Implicits._ +import scutil.implicits._ import scutil.color._ import scutil.gui.GridBagDSL._ import scutil.gui.CasterInstances._ @@ -35,14 +35,13 @@ final class ImageUI(file:File, icon:Option[Icon], thumbnailMaxSize:Int, programH private val imageView = new JLabel(null, null, SwingConstants.CENTER) imageView setBackground rgb"eeeeee".toColor -// imageView.setBorder( -// BorderFactory.createBevelBorder(BevelBorder.RAISED) -// ) imageView setOpaque true - /*### fehlt - imageView.setToolTipText( + /* + BETTER add tooltip + imageView setToolTipText ( file.Name + " (" + TextUtil.human(file.length()) + " bytes)" ) + ) */ imageView setHorizontalTextPosition SwingConstants.CENTER imageView setVerticalTextPosition SwingConstants.CENTER @@ -207,19 +206,6 @@ final class ImageUI(file:File, icon:Option[Icon], thumbnailMaxSize:Int, programH categoriesEditor.getText ) - /* - def setData(imageData:ImageData) { - //this.file = imageData.file - uploadEditor setSelected imageData.upload - nameEditor setText imageData.name - descriptionEditor setText imageData.description - dateEditor setText imageData.date - permissionEditor setText imageData.permission - coordinatesEditor setText imageData.cordinates - categoriesEditor setText imageData.categories - } - */ - private def displayFullImage() { FullImageWindow display (file, programHeading, programIcon) } diff --git a/src/main/scala/commonist/ui/ScrollablePicture.scala b/src/main/scala/commonist/ui/ScrollablePicture.scala index 9ab6eaa..9a70774 100644 --- a/src/main/scala/commonist/ui/ScrollablePicture.scala +++ b/src/main/scala/commonist/ui/ScrollablePicture.scala @@ -26,10 +26,12 @@ final class ScrollablePicture extends JLabel with Scrollable { } def getScrollableBlockIncrement(visibleRect:Rectangle, orientation:Int, direction:Int):Int = { - if (orientation == SwingConstants.HORIZONTAL) + if (orientation == SwingConstants.HORIZONTAL) { visibleRect.width - Constants.FULLSIZE_MAX_UNIT_INCREMENT - else + } + else { visibleRect.height - Constants.FULLSIZE_MAX_UNIT_INCREMENT + } } def getPreferredScrollableViewportSize():Dimension = getPreferredSize diff --git a/src/main/scala/commonist/util/EXIF.scala b/src/main/scala/commonist/util/EXIF.scala index 924e3c7..8fe1430 100644 --- a/src/main/scala/commonist/util/EXIF.scala +++ b/src/main/scala/commonist/util/EXIF.scala @@ -19,9 +19,7 @@ import org.apache.sanselan.formats.tiff.constants.TiffTagConstants._ import org.apache.sanselan.formats.tiff.constants.TiffDirectoryConstants._ import org.apache.sanselan.formats.tiff.constants.GPSTagConstants._ -import scala.util.control.Exception._ - -import scutil.Implicits._ +import scutil.implicits._ import scutil.math.BigRational import scutil.log._ @@ -110,7 +108,7 @@ object EXIF extends Logging { val sum = bigRational(d) Some(bigDecimal(sum)) case x => - DEBUG("unexpected value: " + x) + DEBUG("unexpected value", x) None } private def bigRational(value:RationalNumber):BigRational = BigRational(value.numerator, value.divisor) diff --git a/src/main/scala/commonist/util/Loader.scala b/src/main/scala/commonist/util/Loader.scala index 50baf87..003cb9c 100644 --- a/src/main/scala/commonist/util/Loader.scala +++ b/src/main/scala/commonist/util/Loader.scala @@ -3,7 +3,7 @@ package commonist.util import java.io._ import java.net._ -import scutil.Implicits._ +import scutil.implicits._ import scutil.log._ /** loads resources from a set of URL-paths */ @@ -15,7 +15,7 @@ final class Loader(settingsDir:File, etcDir:File, resourcesDir:File, resourcePre classloaderURL(resourcePrefix, path) noneEffect { DEBUG( "failed to access resource", path, "tried to find in", - settingsDir, etcDir, resourcesDir, "classpath:" + resourcePrefix) + settingsDir, etcDir, resourcesDir, s"classpath:${resourcePrefix}") } def directoryURL(directory:File, path:String):Option[URL] = diff --git a/src/main/scala/commonist/util/Messages.scala b/src/main/scala/commonist/util/Messages.scala index 6116253..3e4f43a 100644 --- a/src/main/scala/commonist/util/Messages.scala +++ b/src/main/scala/commonist/util/Messages.scala @@ -7,7 +7,7 @@ import java.util.Properties import scala.collection.JavaConversions._ -import scutil.Implicits._ +import scutil.implicits._ import scutil.log._ import scutil.io._ @@ -35,12 +35,12 @@ class Messages(defaultURL:URL, userLangURL:Option[URL]) extends Logging { MessageFormat format (get(key), args.map(_.asInstanceOf[AnyRef]) : _*) } catch { case e:Exception => - ERROR("message cannot be used: " + key) + ERROR(s"message cannot be used: ${key}") throw e } private def get(key:String):String = (userLangProps get key) orElse (defaultProps get key) getOrError - ("message not available: " + key) + (s"message not available: ${key}") } diff --git a/src/main/scala/commonist/util/Settings.scala b/src/main/scala/commonist/util/Settings.scala index 3822e60..fae166a 100644 --- a/src/main/scala/commonist/util/Settings.scala +++ b/src/main/scala/commonist/util/Settings.scala @@ -5,7 +5,7 @@ import java.io._ import scala.collection.mutable import scala.collection.JavaConverters._ -import scutil.Implicits._ +import scutil.implicits._ import scutil.log._ import scutil.io._ @@ -40,7 +40,7 @@ final class Settings(file:File) extends Logging { propertiesMap = PropertiesUtil loadFile file } else { - INFO("setting file does not exist: " + file.getPath) + INFO("setting file does not exist", file.getPath) } } diff --git a/src/main/scala/commonist/util/TextComponentUndo.scala b/src/main/scala/commonist/util/TextComponentUndo.scala index 4f61ab7..4952f2d 100644 --- a/src/main/scala/commonist/util/TextComponentUndo.scala +++ b/src/main/scala/commonist/util/TextComponentUndo.scala @@ -11,8 +11,8 @@ import scutil.log._ /** adds undo to a {@link JTextComponent} */ trait TextComponentUndo extends Logging { self:JTextComponent => - private val REDO_KEY_STROKE = KeyStroke.getKeyStroke("control Y") - private val UNDO_KEY_STROKE = KeyStroke.getKeyStroke("control Z") + private val REDO_KEY_STROKE = KeyStroke getKeyStroke "control Y" + private val UNDO_KEY_STROKE = KeyStroke getKeyStroke "control Z" private val REDO_ACTION = "Redo" private val UNDO_ACTION = "Undo" private val LIMIT = 100 @@ -22,11 +22,12 @@ trait TextComponentUndo extends Logging { self:JTextComponent => private val propertyListener = new PropertyChangeListener { def propertyChange(ev:PropertyChangeEvent) { - if (ev.getPropertyName != "document") return - val oldDocument = ev.getOldValue.asInstanceOf[Document] - val newDocument = ev.getNewValue.asInstanceOf[Document] - oldDocument removeUndoableEditListener undoableEditListener - newDocument addUndoableEditListener undoableEditListener + if (ev.getPropertyName == "document") { + val oldDocument = ev.getOldValue.asInstanceOf[Document] + val newDocument = ev.getNewValue.asInstanceOf[Document] + oldDocument removeUndoableEditListener undoableEditListener + newDocument addUndoableEditListener undoableEditListener + } } } diff --git a/src/main/scala/commonist/util/TextUtil2.scala b/src/main/scala/commonist/util/TextUtil2.scala index 3e744b7..4c99b3b 100644 --- a/src/main/scala/commonist/util/TextUtil2.scala +++ b/src/main/scala/commonist/util/TextUtil2.scala @@ -11,15 +11,15 @@ object TextUtil2 { def shortError(t:Throwable):String = t.getClass.getName.replaceAll("^.*\\.", "") + " " + feedToSpace(t.getMessage) /** replaces every linefeeds with a space */ - def feedToSpace(s:String):String = s.replaceAll("\r\n|\r|\n", " ") + def feedToSpace(s:String):String = s replaceAll ("\r\n|\r|\n", " ") /** removes double empty lines */ - def restrictEmptyLines(s:String):String = s.replaceAll("\n\n\n+", "\n\n") + def restrictEmptyLines(s:String):String = s replaceAll ("\n\n\n+", "\n\n") /** removes linefeeds from both ends of a string */ - def trimLF(s:String):String = s.replaceAll("^\\n+", "").replaceAll("\\n+$", "") + def trimLF(s:String):String = s replaceAll ("^\\n+", "") replaceAll ("\\n+$", "") /** concatenates two Strings and inserts a separator if both are non-empty */ def joinNonEmpty(string1:String, string2:String, separator:String):String = - Vector(string1, string2) filter { _.length != 0 } mkString separator + Vector(string1, string2) filter { _.nonEmpty } mkString separator }