From 838698d7b228ec09e6135ff4fa5b9f317d72f882 Mon Sep 17 00:00:00 2001 From: Drew Short Date: Fri, 29 Aug 2014 18:06:25 -0500 Subject: [PATCH] Working on getting selections working in the tile pane. Limited the pagination to 9 pages at a time otherwise weird elipses appear for two digit values. Look into later. Also fixed the config file output to not inuclude comments as they bloated the file needlessly. --- .../engine/util/PropertiesService.scala | 7 +- .../main/resources/fxml/mainapp/MainApp.fxml | 9 +- .../ui/component/ImageTilePane.scala | 137 ++++++++++++++++++ .../ui/controller/AppController.scala | 25 +++- 4 files changed, 168 insertions(+), 10 deletions(-) create mode 100644 gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTilePane.scala 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 e28d3e1..e733248 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 @@ -3,7 +3,7 @@ package com.sothr.imagetools.engine.util import java.io.{File, FileOutputStream, PrintStream} import java.util.Properties -import com.typesafe.config.{Config, ConfigFactory} +import com.typesafe.config.{ConfigRenderOptions, Config, ConfigFactory} import grizzled.slf4j.Logging /* @@ -13,8 +13,9 @@ object PropertiesService extends Logging { private var defaultConf: Config = null private var userConf: Config = null - private var newUserConf: Properties = new Properties() + private val newUserConf: Properties = new Properties() private var version: Version = null + private val configRenderOptions = ConfigRenderOptions.concise().setFormatted(true) def getVersion: Version = this.version @@ -90,7 +91,7 @@ object PropertiesService extends Logging { val out: PrintStream = new PrintStream(new FileOutputStream(location, false)) val userConfToSave = getCleanedMergedUserConf //print to the output stream - out.print(userConfToSave.root.render) + out.print(userConfToSave.root().render(configRenderOptions)) out.flush() out.close() } diff --git a/gui/src/main/resources/fxml/mainapp/MainApp.fxml b/gui/src/main/resources/fxml/mainapp/MainApp.fxml index 969ae59..e6a7a63 100644 --- a/gui/src/main/resources/fxml/mainapp/MainApp.fxml +++ b/gui/src/main/resources/fxml/mainapp/MainApp.fxml @@ -65,7 +65,7 @@ - + @@ -120,7 +120,7 @@ - + @@ -128,7 +128,10 @@ - + + + + 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 new file mode 100644 index 0000000..1d64bf5 --- /dev/null +++ b/gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTilePane.scala @@ -0,0 +1,137 @@ +package com.sothr.imagetools.ui.component + +import java.util +import javafx.collections.{ModifiableObservableListBase, ObservableList} +import javafx.scene.control.MultipleSelectionModel +import javafx.scene.layout.TilePane + +/** + * Custom Tile Pane with a multi selection model + * + * Created by drew on 8/29/14. + */ +class ImageTilePane extends TilePane { + val selectionModel = new ImageTilePaneSelectionModel(this) +} + +/** + * Multiple selection model for ImageTilePane + * + */ +class ImageTilePaneSelectionModel[ImageTile](parentTilePane: ImageTilePane) extends MultipleSelectionModel[ImageTile] { + + val selectedIndexes: ObservableList[Integer] = new ArrayObservableList[Integer]() + + override def getSelectedIndices: ObservableList[Integer] = { + this.selectedIndexes + } + + override def getSelectedItems: ObservableList[ImageTile] = { + val selected = new ArrayObservableList[ImageTile]() + val iterator = selectedIndexes.iterator() + while (iterator.hasNext) { + selected.add(this.parentTilePane.getChildren.get(iterator.next()).asInstanceOf[ImageTile]) + } + selected + } + + override def selectIndices(index: Int, indices: Int*): Unit = { + this.selectedIndexes.clear() + this.selectedIndexes.add(index) + for (i <- indices) { + this.selectedIndexes.add(i) + } + } + + override def selectAll(): Unit = { + this.selectedIndexes.clear() + for (index <- 0 until this.parentTilePane.getChildren.size()) { + this.selectedIndexes.add(index) + } + } + + override def selectFirst(): Unit = { + this.selectedIndexes.clear() + this.selectedIndexes.add(0) + } + + override def selectLast(): Unit = { + this.selectedIndexes.clear() + this.selectedIndexes.add(this.parentTilePane.getChildren.size()-1) + } + + override def clearAndSelect(index: Int): Unit = { + this.selectedIndexes.clear() + this.selectedIndexes.add(index) + } + + override def clearSelection(index: Int): Unit = { + this.selectedIndexes.remove(index) + } + + override def clearSelection(): Unit = { + this.selectedIndexes.clear() + } + + override def selectPrevious(): Unit = { + if (this.selectedIndexes.size == 1) { + val currentIndex = this.selectedIndexes.get(0) + val nextIndex = if (currentIndex < 1) 0 else currentIndex - 1 + this.selectedIndexes.set(0, nextIndex) + } + } + + override def selectNext(): Unit = { + if (this.selectedIndexes.size == 1) { + val currentIndex = this.selectedIndexes.get(0) + val nextIndex = if (currentIndex >= this.parentTilePane.getChildren.size-1) this.parentTilePane.getChildren.size-1 else currentIndex + 1 + this.selectedIndexes.set(0, nextIndex) + } + } + + override def select(index: Int): Unit = { + this.selectedIndexes.clear() + this.selectedIndexes.add(index) + } + + override def select(obj: ImageTile): Unit = { + if (this.parentTilePane.getChildren.contains(obj)) { + this.selectedIndexes.clear() + this.selectedIndexes.add(this.parentTilePane.getChildren.indexOf(obj)) + } + } + + override def isEmpty: Boolean = { + this.parentTilePane.getChildren.isEmpty + } + + override def isSelected(index: Int): Boolean = { + this.selectedIndexes.contains(index) + } +} + +class ArrayObservableList[E] extends ModifiableObservableListBase[E] { + + val delegate: util.ArrayList[E] = new util.ArrayList[E]() + + def get(index: Int): E = { + delegate.get(index) + } + + def size = { + delegate.size + } + + def doAdd (index: Int, element: E) = { + delegate.add(index, element) + } + + def doSet (index: Int, element: E): E = { + delegate.set(index, element) + } + + def doRemove (index: Int): E = { + delegate.remove(index) + } + +} \ No newline at end of file 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 336489a..c412dc0 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 @@ -17,7 +17,7 @@ import akka.actor._ import com.sothr.imagetools.engine._ import com.sothr.imagetools.engine.image.{Image, SimilarImages} import com.sothr.imagetools.engine.util.{PropertiesService, ResourceLoader} -import com.sothr.imagetools.ui.component.ImageTileFactory +import com.sothr.imagetools.ui.component.{ImageTilePane, ImageTileFactory} import grizzled.slf4j.Logging import org.markdown4j.Markdown4jProcessor @@ -36,6 +36,7 @@ class AppController extends Logging { //Define controls @FXML var rootPane: AnchorPane = null @FXML var rootMenuBar: MenuBar = null + @FXML var scrollPane: ScrollPane = null @FXML var imageTilePane: TilePane = null @FXML var tagListView: ListView[String] = null @@ -76,7 +77,7 @@ class AppController extends Logging { // set the default images per page if it doesn't exist yet if (!PropertiesService.has("app.ui.thumbsPerPage")) { - PropertiesService.set("app.ui.thumbsPerPage", "50") + PropertiesService.set("app.ui.thumbsPerPage", "100") } // configure the page factory @@ -89,6 +90,22 @@ class AppController extends Logging { } }) + //override the imageTilePane + val newImageTilePane = new ImageTilePane() + newImageTilePane.setHgap(this.imageTilePane.getHgap) + newImageTilePane.setVgap(this.imageTilePane.getVgap) + newImageTilePane.setMinHeight(this.imageTilePane.getMinHeight) + newImageTilePane.setMinWidth(this.imageTilePane.getMinWidth) + newImageTilePane.setMaxHeight(this.imageTilePane.getMaxHeight) + newImageTilePane.setMaxWidth(this.imageTilePane.getMaxWidth) + newImageTilePane.setPrefColumns(this.imageTilePane.getPrefColumns) + newImageTilePane.setPrefRows(this.imageTilePane.getPrefRows) + newImageTilePane.setPrefTileHeight(this.imageTilePane.getPrefTileHeight) + newImageTilePane.setPrefTileWidth(this.imageTilePane.getPrefTileWidth) + newImageTilePane.setTileAlignment(this.imageTilePane.getTileAlignment) + this.scrollPane.setContent(newImageTilePane) + this.imageTilePane = newImageTilePane + //test //val testImage = new Image() //testImage.setThumbnailPath("test.jpg") @@ -225,14 +242,14 @@ class AppController extends Logging { 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 itemsPerPage = PropertiesService.get("app.ui.thumbsPerPage", "100").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 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 and populate the scrollpane