Browse Source

Paginated the results for faster display and resizing.

Moved around some app configurations.
Worked on making the GUI a bit more usable.
master
Drew Short 10 years ago
parent
commit
78804a305f
  1. 5
      gui/src/main/resources/fxml/mainapp/MainApp.fxml
  2. 5
      gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTileFactory.scala
  3. 95
      gui/src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala

5
gui/src/main/resources/fxml/mainapp/MainApp.fxml

@ -107,9 +107,9 @@
<children> <children>
<ToolBar maxHeight="30.0" minHeight="30.0" prefHeight="30.0" VBox.vgrow="ALWAYS"> <ToolBar maxHeight="30.0" minHeight="30.0" prefHeight="30.0" VBox.vgrow="ALWAYS">
<items> <items>
<Label text="Currect Directory:" />
<Label text="Current Directory:" />
<Separator orientation="VERTICAL" prefHeight="200.0" /> <Separator orientation="VERTICAL" prefHeight="200.0" />
<Label text="&lt;CURRENT DIRECTORY&gt;" />
<Label fx:id="currentDirectoryLabel" text="&lt;CURRENT DIRECTORY&gt;" />
</items> </items>
<VBox.margin> <VBox.margin>
<Insets bottom="-5.0" /> <Insets bottom="-5.0" />
@ -123,6 +123,7 @@
<Insets /> <Insets />
</VBox.margin> </VBox.margin>
</ScrollPane> </ScrollPane>
<Pagination fx:id="paginator" disable="true" maxHeight="40.0" maxPageIndicatorCount="30" minHeight="40.0" pageCount="1" prefHeight="30.0" />
</children> </children>
</VBox> </VBox>
</items> </items>

5
gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTileFactory.scala

@ -1,6 +1,7 @@
package com.sothr.imagetools.ui.component package com.sothr.imagetools.ui.component
import java.io.FileInputStream
import java.awt.Desktop
import java.io.{File, FileInputStream}
import javafx.event.EventHandler import javafx.event.EventHandler
import javafx.geometry.{Insets, Pos} import javafx.geometry.{Insets, Pos}
import javafx.scene.control.{Label, Tooltip} import javafx.scene.control.{Label, Tooltip}
@ -33,7 +34,7 @@ object ImageTileFactory extends Logging {
if (event.isPrimaryButtonDown) { if (event.isPrimaryButtonDown) {
//double click //double click
if (event.getClickCount == 2) { if (event.getClickCount == 2) {
Desktop.getDesktop.open(new File(image.getImagePath))
} else { } else {
} }

95
gui/src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala

@ -6,20 +6,23 @@ import java.util.Scanner
import javafx.application.Platform import javafx.application.Platform
import javafx.event.ActionEvent import javafx.event.ActionEvent
import javafx.fxml.FXML import javafx.fxml.FXML
import javafx.scene.control.{Label, ProgressBar}
import javafx.scene.control._
import javafx.scene.layout.{VBox, TilePane, AnchorPane}
import javafx.scene.text.{Text, TextAlignment} import javafx.scene.text.{Text, TextAlignment}
import javafx.scene.web.WebView import javafx.scene.web.WebView
import javafx.scene.{Group, Node, Scene} import javafx.scene.{Group, Node, Scene}
import javafx.stage.{DirectoryChooser, Stage, StageStyle} import javafx.stage.{DirectoryChooser, Stage, StageStyle}
import javafx.util.Callback
import akka.actor._ import akka.actor._
import com.sothr.imagetools.engine.image.{SimilarImages, Image}
import com.sothr.imagetools.engine.image.{Image, SimilarImages}
import com.sothr.imagetools.engine.util.{PropertiesService, ResourceLoader} import com.sothr.imagetools.engine.util.{PropertiesService, ResourceLoader}
import com.sothr.imagetools.engine._ import com.sothr.imagetools.engine._
import com.sothr.imagetools.ui.component.ImageTileFactory import com.sothr.imagetools.ui.component.ImageTileFactory
import grizzled.slf4j.Logging import grizzled.slf4j.Logging
import org.markdown4j.Markdown4jProcessor import org.markdown4j.Markdown4jProcessor
import scala.collection.mutable
import scala.concurrent._ import scala.concurrent._
import scala.util.{Failure, Success} import scala.util.{Failure, Success}
import ExecutionContext.Implicits.global import ExecutionContext.Implicits.global
@ -32,28 +35,31 @@ import ExecutionContext.Implicits.global
class AppController extends Logging { class AppController extends Logging {
//Define controls //Define controls
@FXML var rootPane: javafx.scene.layout.AnchorPane = null
@FXML var rootMenuBar: javafx.scene.control.MenuBar = null
@FXML var imageTilePane: javafx.scene.layout.TilePane = null
@FXML var tagListView: javafx.scene.control.ListView[String] = null
@FXML var rootPane: AnchorPane = null
@FXML var rootMenuBar: MenuBar = null
@FXML var imageTilePane: TilePane = null
@FXML var tagListView: ListView[String] = null
// Labels // Labels
@FXML var selectedDirectoryLabel: javafx.scene.control.Label = null
@FXML var progressLabel: javafx.scene.control.Label = null
@FXML var selectedDirectoryLabel: Label = null
@FXML var currentDirectoryLabel: Label = null
@FXML var progressLabel: Label = null
// Others // Others
@FXML var progressBar: javafx.scene.control.ProgressBar = null
@FXML var progressBar: ProgressBar = null
@FXML var paginator: Pagination = null
// Engine // Engine
val engine: Engine = new ConcurrentEngine() val engine: Engine = new ConcurrentEngine()
// Current State // Current State
var currentDirectory: String = "." var currentDirectory: String = "."
var currentImages: List[Image] = List[Image]()
@FXML def initialize() = { @FXML def initialize() = {
if (PropertiesService.has("lastPath")) {
currentDirectory = PropertiesService.get("lastPath", ".")
selectedDirectoryLabel.setText(PropertiesService.get("lastPath", ""))
if (PropertiesService.has("app.ui.lastPath")) {
currentDirectory = PropertiesService.get("app.ui.lastPath", ".")
selectedDirectoryLabel.setText(PropertiesService.get("app.ui.lastPath", ""))
} }
//setup the engine listener //setup the engine listener
@ -68,6 +74,21 @@ class AppController extends Logging {
// Initialize the progress label // Initialize the progress label
guiListener ! SubmitMessage("Initialized System... Ready!") guiListener ! SubmitMessage("Initialized System... Ready!")
// set the default images per page if it doesn't exist yet
if (!PropertiesService.has("app.ui.thumbsPerPage")) {
PropertiesService.set("app.ui.thumbsPerPage", "50")
}
// configure the page factory
paginator.setPageFactory(new Callback[Integer, Node]() {
override def call(pageIndex: Integer): Node = {
// do all of our display logic
showPage(pageIndex)
// override behavior to display anything
new VBox()
}
})
//test //test
//val testImage = new Image() //val testImage = new Image()
//testImage.setThumbnailPath("test.jpg") //testImage.setThumbnailPath("test.jpg")
@ -136,11 +157,13 @@ class AppController extends Logging {
selectedDirectoryLabel.setText(selectedDirectory.getAbsolutePath) selectedDirectoryLabel.setText(selectedDirectory.getAbsolutePath)
currentDirectory = selectedDirectory.getAbsolutePath currentDirectory = selectedDirectory.getAbsolutePath
PropertiesService.set("lastPath", selectedDirectory.getAbsolutePath)
PropertiesService.set("app.ui.lastPath", selectedDirectory.getAbsolutePath)
this.currentDirectoryLabel.setText(selectedDirectory.getAbsolutePath)
} }
@FXML @FXML
def showAllImages(event: ActionEvent) = { def showAllImages(event: ActionEvent) = {
resetPaginator()
imageTilePane.getChildren.setAll(new ArrayList[Node]()) imageTilePane.getChildren.setAll(new ArrayList[Node]())
val f: Future[List[Image]] = Future { val f: Future[List[Image]] = Future {
engine.getImagesForDirectory(currentDirectory) engine.getImagesForDirectory(currentDirectory)
@ -153,10 +176,7 @@ class AppController extends Logging {
// This is important since UI updates can only happen on that thread // This is important since UI updates can only happen on that thread
Platform.runLater(new Runnable() { Platform.runLater(new Runnable() {
override def run() { override def run() {
for (image <- images) {
debug(s"Adding image ${image.toString} to app")
imageTilePane.getChildren.add(ImageTileFactory.get(image))
}
setPagesContent(images)
} }
}) })
case Failure(t) => case Failure(t) =>
@ -166,6 +186,7 @@ class AppController extends Logging {
@FXML @FXML
def showSimilarImages(event: ActionEvent) = { def showSimilarImages(event: ActionEvent) = {
resetPaginator()
imageTilePane.getChildren.setAll(new ArrayList[Node]()) imageTilePane.getChildren.setAll(new ArrayList[Node]())
val f: Future[List[SimilarImages]] = Future { val f: Future[List[SimilarImages]] = Future {
@ -177,11 +198,14 @@ class AppController extends Logging {
info(s"Displaying ${similarImages.length} similar images") info(s"Displaying ${similarImages.length} similar images")
Platform.runLater(new Runnable() { Platform.runLater(new Runnable() {
override def run() { override def run() {
val tempImages = new mutable.MutableList[Image]()
for (similarImage <- similarImages) { for (similarImage <- similarImages) {
debug(s"Adding similar images ${similarImage.rootImage.toString} to app") debug(s"Adding similar images ${similarImage.rootImage.toString} to app")
tempImages += similarImage.rootImage
imageTilePane.getChildren.add(ImageTileFactory.get(similarImage.rootImage)) imageTilePane.getChildren.add(ImageTileFactory.get(similarImage.rootImage))
similarImage.similarImages.foreach(image => imageTilePane.getChildren.add(ImageTileFactory.get(image)))
similarImage.similarImages.foreach(image => tempImages += image)
} }
setPagesContent(tempImages.toList)
} }
}) })
case Failure(t) => case Failure(t) =>
@ -191,6 +215,41 @@ class AppController extends Logging {
//endregion //endregion
//region pagination
def resetPaginator() = {
this.paginator.setDisable(true)
this.paginator.setPageCount(1)
}
def setPagesContent(images: List[Image]) = {
this.currentImages = images
//set the appropriate size for the pagination
val itemsPerPage = PropertiesService.get("app.ui.thumbsPerPage", "50").toInt
val pageNum = Math.ceil(this.currentImages.size.toFloat / itemsPerPage).toInt
this.paginator.setPageCount(pageNum)
this.paginator.setDisable(false)
}
def showPage(pageIndex: Integer) = {
val itemsPerPage = PropertiesService.get("app.ui.thumbsPerPage", "50").toInt
val startIndex = pageIndex * itemsPerPage
val endIndex = if ((startIndex + itemsPerPage) > this.currentImages.size) this.currentImages.length else (startIndex + itemsPerPage)
//clear and populate the scrollpane
imageTilePane.getChildren.setAll(new ArrayList[Node]())
val images = this.currentImages.slice(startIndex, endIndex)
Platform.runLater(new Runnable() {
override def run() {
for (image <- images) {
debug(s"Adding image ${image.toString} to app")
imageTilePane.getChildren.add(ImageTileFactory.get(image))
}
}
})
}
//endregion
//todo: include a templating engine for rendering information //todo: include a templating engine for rendering information
//todo: show a dialog that is rendered from markdown content //todo: show a dialog that is rendered from markdown content

Loading…
Cancel
Save