From a81ad158e0e240a569b9c4feb821dd5234691dd4 Mon Sep 17 00:00:00 2001 From: Drew Short Date: Fri, 29 Aug 2014 19:10:31 -0500 Subject: [PATCH] Added highlighting boxes around selection. Shift click for multi selection. Single click for single selection. Need to work on context menus next --- .../imagetools/ui/component/ImageTile.scala | 60 +++++++++++++------ .../ui/component/ImageTileFactory.scala | 5 +- .../ui/component/ImageTilePane.scala | 46 +++++++++++++- .../ui/controller/AppController.scala | 8 +-- 4 files changed, 93 insertions(+), 26 deletions(-) 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 9845805..55d3c0a 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 @@ -2,8 +2,8 @@ package com.sothr.imagetools.ui.component import java.io.FileInputStream import javafx.event.EventHandler -import javafx.geometry.Pos -import javafx.scene.control.{Tooltip, Label} +import javafx.geometry.{Orientation, Insets, Pos} +import javafx.scene.control.{Separator, Tooltip, Label} import javafx.scene.image.{ImageView} import javafx.scene.input.MouseEvent import javafx.scene.layout.VBox @@ -16,32 +16,53 @@ import resource._ * * Created by drew on 8/22/14. */ -class ImageTile(thumbnailWidth: Integer, image: com.sothr.imagetools.engine.image.Image) extends VBox with Logging { - val imageData: com.sothr.imagetools.engine.image.Image = image - val preferedTileSize = (thumbnailWidth + 32).toDouble +class ImageTile(thumbnailWidth: Integer, + image: com.sothr.imagetools.engine.image.Image, + imageTilePane: ImageTilePane) extends VBox with Logging { + val thisTile = this + val imageData = image + val preferedTileWidth = (thumbnailWidth + 8).toDouble + val preferedTileHeight = (thumbnailWidth + 32).toDouble //set tile size - this.setPrefSize(preferedTileSize, preferedTileSize) - this.setMinSize(preferedTileSize, preferedTileSize) - this.setMaxSize(preferedTileSize, preferedTileSize) + this.setPrefSize(preferedTileWidth, preferedTileHeight) + this.setMinSize(preferedTileWidth, preferedTileHeight) + this.setMaxSize(preferedTileWidth, preferedTileHeight) - this.setAlignment(Pos.TOP_CENTER) + //set padding on the tiles + //this.setPadding(new Insets(10.0d,0.0d,10.0d,0.0d)) + + this.setAlignment(Pos.CENTER) this.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler[MouseEvent] { override def handle(event: MouseEvent): Unit = { - if (event.isPrimaryButtonDown) { - //double click - 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)) - } else { + if (event.isShiftDown) { + //multiple selection + imageTilePane.addImageSelected(thisTile) + } + else { + if (event.isPrimaryButtonDown) { + imageTilePane.imageSelected(thisTile) + //double click + 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)) + } else { + } + } else if (event.isSecondaryButtonDown) { + //right click context menu } - } else if (event.isSecondaryButtonDown) { - //right click context menu } } }) + //Separator + val separator = new Separator() + separator.setOrientation(Orientation.HORIZONTAL) + separator.setMaxHeight(5.0d) + separator.setVisible(false) + this.getChildren.add(separator) + // Image val genImageView = new ImageView() debug(s"Getting thumbnail from: ${image.getThumbnailPath}") @@ -63,6 +84,9 @@ class ImageTile(thumbnailWidth: Integer, image: com.sothr.imagetools.engine.imag val imageLabel = new Label() imageLabel.setText(s"${image.getHeight}x${image.getWidth}") imageLabel.setWrapText(true) + imageLabel.setMaxHeight(32d) + imageLabel.setMaxWidth(preferedTileWidth-2) + imageLabel.setAlignment(Pos.BOTTOM_CENTER) //Tooltip val tooltip = new Tooltip() diff --git a/gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTileFactory.scala b/gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTileFactory.scala index 017eaab..030dd9e 100644 --- a/gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTileFactory.scala +++ b/gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTileFactory.scala @@ -1,6 +1,7 @@ package com.sothr.imagetools.ui.component import javafx.geometry.Insets +import javafx.scene.layout.TilePane import com.sothr.imagetools.engine.util.PropertiesService import grizzled.slf4j.Logging @@ -12,9 +13,9 @@ import grizzled.slf4j.Logging */ object ImageTileFactory extends Logging { - def get(image: com.sothr.imagetools.engine.image.Image): ImageTile = { + def get(image: com.sothr.imagetools.engine.image.Image, pane: TilePane): ImageTile = { val thumbnailWidth = PropertiesService.get("app.thumbnail.size","128").toInt - val imageTile = new ImageTile(thumbnailWidth, image) + val imageTile = new ImageTile(thumbnailWidth, image, pane.asInstanceOf[ImageTilePane]) //set padding imageTile.setPadding(new Insets(2, 2, 2, 2)) 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 1d64bf5..465b27b 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 @@ -3,7 +3,8 @@ package com.sothr.imagetools.ui.component import java.util import javafx.collections.{ModifiableObservableListBase, ObservableList} import javafx.scene.control.MultipleSelectionModel -import javafx.scene.layout.TilePane +import javafx.scene.layout._ +import javafx.scene.paint.{Color, Paint} /** * Custom Tile Pane with a multi selection model @@ -12,6 +13,14 @@ import javafx.scene.layout.TilePane */ class ImageTilePane extends TilePane { val selectionModel = new ImageTilePaneSelectionModel(this) + + def imageSelected(imageTile: ImageTile) = { + this.selectionModel.clearAndSelect(this.getChildren.indexOf(imageTile)) + } + + def addImageSelected(imageTile: ImageTile) = { + this.selectionModel.select(this.getChildren.indexOf(imageTile)) + } } /** @@ -36,32 +45,43 @@ class ImageTilePaneSelectionModel[ImageTile](parentTilePane: ImageTilePane) exte } override def selectIndices(index: Int, indices: Int*): Unit = { + clearSelectionFormatting this.selectedIndexes.clear() + setSelectionFormatting(index) this.selectedIndexes.add(index) for (i <- indices) { + setSelectionFormatting(i) this.selectedIndexes.add(i) } } override def selectAll(): Unit = { + clearSelectionFormatting this.selectedIndexes.clear() for (index <- 0 until this.parentTilePane.getChildren.size()) { + setSelectionFormatting(index) this.selectedIndexes.add(index) } } override def selectFirst(): Unit = { + clearSelectionFormatting this.selectedIndexes.clear() + setSelectionFormatting(0) this.selectedIndexes.add(0) } override def selectLast(): Unit = { + clearSelectionFormatting this.selectedIndexes.clear() + setSelectionFormatting(this.parentTilePane.getChildren.size()-1) this.selectedIndexes.add(this.parentTilePane.getChildren.size()-1) } override def clearAndSelect(index: Int): Unit = { + clearSelectionFormatting this.selectedIndexes.clear() + setSelectionFormatting(index) this.selectedIndexes.add(index) } @@ -70,6 +90,7 @@ class ImageTilePaneSelectionModel[ImageTile](parentTilePane: ImageTilePane) exte } override def clearSelection(): Unit = { + clearSelectionFormatting this.selectedIndexes.clear() } @@ -90,13 +111,15 @@ class ImageTilePaneSelectionModel[ImageTile](parentTilePane: ImageTilePane) exte } override def select(index: Int): Unit = { - this.selectedIndexes.clear() + setSelectionFormatting(index) this.selectedIndexes.add(index) } override def select(obj: ImageTile): Unit = { if (this.parentTilePane.getChildren.contains(obj)) { + clearSelectionFormatting this.selectedIndexes.clear() + setSelectionFormatting(obj) this.selectedIndexes.add(this.parentTilePane.getChildren.indexOf(obj)) } } @@ -108,6 +131,25 @@ class ImageTilePaneSelectionModel[ImageTile](parentTilePane: ImageTilePane) exte override def isSelected(index: Int): Boolean = { this.selectedIndexes.contains(index) } + + private def clearSelectionFormatting = { + val iterator = this.parentTilePane.getChildren.iterator() + while (iterator.hasNext) { + //remove the selection styling + val imageTile: VBox = iterator.next().asInstanceOf[VBox] + imageTile.setBorder(Border.EMPTY) + } + } + + private def setSelectionFormatting(index: Int): Unit = { + setSelectionFormatting(this.parentTilePane.getChildren.get(index).asInstanceOf[ImageTile]) + } + + private def setSelectionFormatting(imageTile: ImageTile): Unit = { + val borderStroke = new BorderStroke(Color.BLUE, BorderStrokeStyle.SOLID, CornerRadii.EMPTY,BorderStroke.THIN) + imageTile.asInstanceOf[VBox].setBorder(new Border(borderStroke)) + } + } class ArrayObservableList[E] extends ModifiableObservableListBase[E] { 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 c412dc0..ea895ae 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 @@ -100,8 +100,8 @@ class AppController extends Logging { 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.setPrefTileHeight(this.imageTilePane.getPrefTileHeight) + //newImageTilePane.setPrefTileWidth(this.imageTilePane.getPrefTileWidth) newImageTilePane.setTileAlignment(this.imageTilePane.getTileAlignment) this.scrollPane.setContent(newImageTilePane) this.imageTilePane = newImageTilePane @@ -219,7 +219,7 @@ class AppController extends Logging { for (similarImage <- similarImages) { 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, imageTilePane)) similarImage.similarImages.foreach(image => tempImages += image) } setPagesContent(tempImages.toList) @@ -259,7 +259,7 @@ class AppController extends Logging { override def run() { for (image <- images) { debug(s"Adding image ${image.toString} to app") - imageTilePane.getChildren.add(ImageTileFactory.get(image)) + imageTilePane.getChildren.add(ImageTileFactory.get(image, imageTilePane)) } } })