diff --git a/engine/src/main/java/com/sothr/imagetools/engine/AppConfig.java b/engine/src/main/java/com/sothr/imagetools/engine/AppConfig.java
index 94ff970..ae580ba 100644
--- a/engine/src/main/java/com/sothr/imagetools/engine/AppConfig.java
+++ b/engine/src/main/java/com/sothr/imagetools/engine/AppConfig.java
@@ -94,6 +94,7 @@ public class AppConfig {
String message = fromFile ? "From File" : "From Defaults";
logger.info(String.format("Configured Logger %s", message));
logger.info(String.format("Detected Version: %s of Image Tools", PropertiesService.getVersion().toString()));
+ logger.info(String.format("Running on %s, %s, %s",PropertiesService.OS(), PropertiesService.OS_VERSION(),PropertiesService.OS_ARCH()));
}
//Only configure logging from the default file once
diff --git a/engine/src/main/scala/com/sothr/imagetools/engine/util/PropertiesService.scala b/engine/src/main/scala/com/sothr/imagetools/engine/util/PropertiesService.scala
index e733248..d4372b5 100644
--- a/engine/src/main/scala/com/sothr/imagetools/engine/util/PropertiesService.scala
+++ b/engine/src/main/scala/com/sothr/imagetools/engine/util/PropertiesService.scala
@@ -38,6 +38,11 @@ object PropertiesService extends Logging {
var pHashWeight = 0.0f
var usePhash = false
+ //OS information
+ val OS = System.getProperty("os.name", "UNKNOWN")
+ val OS_VERSION = System.getProperty("os.version", "UNKNOWN")
+ val OS_ARCH = System.getProperty("os.arch", "UNKNOWN")
+
/*
* Load the properties file from the specified location
*/
diff --git a/gui/src/main/resources/fxml/mainapp/MainApp.fxml b/gui/src/main/resources/fxml/mainapp/MainApp.fxml
index 2d48599..f7ef02c 100644
--- a/gui/src/main/resources/fxml/mainapp/MainApp.fxml
+++ b/gui/src/main/resources/fxml/mainapp/MainApp.fxml
@@ -2,6 +2,7 @@
+
@@ -128,9 +129,9 @@
-
+
-
+
diff --git a/gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTile.scala b/gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTile.scala
index f64061d..ae8a02d 100644
--- a/gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTile.scala
+++ b/gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTile.scala
@@ -1,6 +1,7 @@
package com.sothr.imagetools.ui.component
-import java.io.FileInputStream
+import java.awt.Desktop
+import java.io.{File, FileInputStream}
import javafx.event.{EventType, EventHandler}
import javafx.geometry.{Orientation, Insets, Pos}
import javafx.scene.control.{Separator, Tooltip, Label}
@@ -8,6 +9,7 @@ import javafx.scene.image.{ImageView}
import javafx.scene.input.{PickResult, ContextMenuEvent, MouseEvent}
import javafx.scene.layout.VBox
+import com.sothr.imagetools.ui.util.FileUtil
import grizzled.slf4j.Logging
import resource._
@@ -37,6 +39,9 @@ class ImageTile(thumbnailWidth: Integer,
if (event.isShiftDown) {
//multiple selection
imageTilePane.addImageSelected(thisTile)
+ //remove individual images with control
+ } else if (event.isControlDown) {
+ imageTilePane.removeImageSelected(thisTile)
}
else {
if (event.isPrimaryButtonDown) {
@@ -45,13 +50,14 @@ class ImageTile(thumbnailWidth: Integer,
if (event.getClickCount == 2) {
// Look into http://stackoverflow.com/questions/228477/how-do-i-programmatically-determine-operating-system-in-java
// for proper multi-platform opening support
- //Desktop.getDesktop.open(new File(image.getImagePath))
+ FileUtil.openInEditor(new File(image.getImagePath))
} else {
}
} else if (event.isSecondaryButtonDown) {
//right click context menu
debug("Requesting Context Menu")
+ imageTilePane.addImageSelected(thisTile)
val contextMenuEvent = new ContextMenuEvent(
thisTile,
thisTile,
diff --git a/gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTilePane.scala b/gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTilePane.scala
index b4e01ae..41f1e18 100644
--- a/gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTilePane.scala
+++ b/gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTilePane.scala
@@ -88,6 +88,15 @@ class ImageTilePane extends TilePane with Logging {
def addImageSelected(imageTile: ImageTile) = {
this.selectionModel.select(this.getChildren.indexOf(imageTile))
}
+
+ def removeImageSelected(imageTile: ImageTile) = {
+ this.selectionModel.clearSelection(this.getChildren.indexOf(imageTile))
+ }
+
+ def clearSelection() = {
+ this.selectionModel.clearSelection()
+ }
+
}
/**
@@ -153,7 +162,11 @@ class ImageTilePaneSelectionModel[ImageTile](parentTilePane: ImageTilePane) exte
}
override def clearSelection(index: Int): Unit = {
- this.selectedIndexes.remove(index)
+ val i = this.selectedIndexes.indexOf(index)
+ if (i >= 0) {
+ clearSelectionFormatting(index)
+ this.selectedIndexes.remove(i)
+ }
}
override def clearSelection(): Unit = {
@@ -178,8 +191,11 @@ class ImageTilePaneSelectionModel[ImageTile](parentTilePane: ImageTilePane) exte
}
override def select(index: Int): Unit = {
- setSelectionFormatting(index)
- this.selectedIndexes.add(index)
+ //can only select once
+ if (! this.selectedIndexes.contains(index)) {
+ setSelectionFormatting(index)
+ this.selectedIndexes.add(index)
+ }
}
override def select(obj: ImageTile): Unit = {
@@ -199,6 +215,11 @@ class ImageTilePaneSelectionModel[ImageTile](parentTilePane: ImageTilePane) exte
this.selectedIndexes.contains(index)
}
+ private def clearSelectionFormatting(index: Int) = {
+ val tile = this.parentTilePane.getChildren.get(index).asInstanceOf[VBox]
+ tile.setBorder(Border.EMPTY)
+ }
+
private def clearSelectionFormatting() = {
val iterator = this.parentTilePane.getChildren.iterator()
while (iterator.hasNext) {
@@ -212,7 +233,7 @@ class ImageTilePaneSelectionModel[ImageTile](parentTilePane: ImageTilePane) exte
setSelectionFormatting(this.parentTilePane.getChildren.get(index).asInstanceOf[ImageTile])
}
- private def setSelectionFormatting(imageTile: ImageTile): Unit = {
+ private def setSelectionFormatting(imageTile: ImageTile) = {
val borderStroke = new BorderStroke(Color.BLUE, BorderStrokeStyle.SOLID, CornerRadii.EMPTY,BorderStroke.THIN)
imageTile.asInstanceOf[VBox].setBorder(new Border(borderStroke))
}
diff --git a/gui/src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala b/gui/src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala
index 4dd7263..bdedbe7 100644
--- a/gui/src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala
+++ b/gui/src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala
@@ -80,6 +80,9 @@ class AppController extends Logging {
PropertiesService.set("app.ui.thumbsPerPage", "100")
}
+ //setup the paginator
+ //font size doesn't increase the size of the buttons
+ //paginator.setStyle("-fx-font-size:13;")
// configure the page factory
paginator.setPageFactory(new Callback[Integer, Node]() {
override def call(pageIndex: Integer): Node = {
@@ -188,7 +191,8 @@ class AppController extends Logging {
resetPaginator()
getImageTilePane.getChildren.setAll(new java.util.ArrayList[Node]())
val f: Future[List[Image]] = Future {
- engine.getImagesForDirectory(currentDirectory, recursive = doRecursiveProcessing.isSelected)
+ val images = engine.getImagesForDirectory(currentDirectory, recursive = doRecursiveProcessing.isSelected)
+ images.sortWith((x,y) => x.imagePath < y.imagePath)
}
f onComplete {
@@ -212,22 +216,23 @@ class AppController extends Logging {
resetPaginator()
imageTilePane.getChildren.setAll(new java.util.ArrayList[Node]())
- val f: Future[List[SimilarImages]] = Future {
- engine.getSimilarImagesForDirectory(currentDirectory, recursive = doRecursiveProcessing.isSelected)
+ val f: Future[List[Image]] = Future {
+ val similarImages = engine.getSimilarImagesForDirectory(currentDirectory, recursive = doRecursiveProcessing.isSelected)
+ val tempImages = new mutable.MutableList[Image]()
+ for (similarImage <- similarImages) {
+ debug(s"Adding similar images ${similarImage.rootImage.toString} to app")
+ tempImages += similarImage.rootImage
+ similarImage.similarImages.foreach(image => tempImages += image)
+ }
+ tempImages.toList.sortWith((x,y) => x.imagePath < y.imagePath)
}
f onComplete {
- case Success(similarImages) =>
- info(s"Displaying ${similarImages.length} similar images")
+ case Success(images) =>
+ info(s"Displaying ${images.length} similar images")
Platform.runLater(new Runnable() {
override def run() {
- val tempImages = new mutable.MutableList[Image]()
- for (similarImage <- similarImages) {
- debug(s"Adding similar images ${similarImage.rootImage.toString} to app")
- tempImages += similarImage.rootImage
- similarImage.similarImages.foreach(image => tempImages += image)
- }
- setPagesContent(tempImages.toList)
+ setPagesContent(images)
showPage(0)
}
})
@@ -246,7 +251,7 @@ class AppController extends Logging {
}
def setPagesContent(images: List[Image]) = {
- this.currentImages = images.sortWith((x,y) => x.imagePath < y.imagePath)
+ this.currentImages = images
//set the appropriate size for the pagination
val itemsPerPage = PropertiesService.get("app.ui.thumbsPerPage", "100").toInt
val pageNum = Math.ceil(this.currentImages.size.toFloat / itemsPerPage).toInt
@@ -258,6 +263,8 @@ class AppController extends Logging {
val itemsPerPage = PropertiesService.get("app.ui.thumbsPerPage", "100").toInt
val startIndex = pageIndex * itemsPerPage
val endIndex = if ((startIndex + itemsPerPage) > this.currentImages.size) this.currentImages.length else startIndex + itemsPerPage
+ //clear any selections
+ getImageTilePane.asInstanceOf[ImageTilePane].clearSelection()
//clear and populate the scrollpane
getImageTilePane.getChildren.setAll(new java.util.ArrayList[Node]())
val images = this.currentImages.slice(startIndex, endIndex)
diff --git a/gui/src/main/scala/com/sothr/imagetools/ui/util/FileUtil.scala b/gui/src/main/scala/com/sothr/imagetools/ui/util/FileUtil.scala
new file mode 100644
index 0000000..317b169
--- /dev/null
+++ b/gui/src/main/scala/com/sothr/imagetools/ui/util/FileUtil.scala
@@ -0,0 +1,21 @@
+package com.sothr.imagetools.ui.util
+
+import java.awt.Desktop
+import java.io.File
+
+import com.sothr.imagetools.engine.util.PropertiesService
+import grizzled.slf4j.Logging
+
+/**
+ * Created by Drew Short on 8/31/2014.
+ */
+object FileUtil extends Logging {
+
+ def openInEditor(file: File) = {
+ PropertiesService.OS.toLowerCase match {
+ // Open file on windows
+ case os if os.startsWith("windows") => Desktop.getDesktop.open(file)
+ case default => error(s"Do not know how to open editor for OS: ${PropertiesService.OS}, ${PropertiesService.OS_VERSION}, ${PropertiesService.OS_ARCH}")
+ }
+ }
+}