Browse Source

Added highlighting boxes around selection. Shift click for multi selection. Single click for single selection. Need to work on context menus next

master
Drew Short 10 years ago
parent
commit
a81ad158e0
  1. 60
      gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTile.scala
  2. 5
      gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTileFactory.scala
  3. 46
      gui/src/main/scala/com/sothr/imagetools/ui/component/ImageTilePane.scala
  4. 8
      gui/src/main/scala/com/sothr/imagetools/ui/controller/AppController.scala

60
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 java.io.FileInputStream
import javafx.event.EventHandler 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.image.{ImageView}
import javafx.scene.input.MouseEvent import javafx.scene.input.MouseEvent
import javafx.scene.layout.VBox import javafx.scene.layout.VBox
@ -16,32 +16,53 @@ import resource._
* *
* Created by drew on 8/22/14. * 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 //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] { this.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler[MouseEvent] {
override def handle(event: MouseEvent): Unit = { 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 // Image
val genImageView = new ImageView() val genImageView = new ImageView()
debug(s"Getting thumbnail from: ${image.getThumbnailPath}") 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() val imageLabel = new Label()
imageLabel.setText(s"${image.getHeight}x${image.getWidth}") imageLabel.setText(s"${image.getHeight}x${image.getWidth}")
imageLabel.setWrapText(true) imageLabel.setWrapText(true)
imageLabel.setMaxHeight(32d)
imageLabel.setMaxWidth(preferedTileWidth-2)
imageLabel.setAlignment(Pos.BOTTOM_CENTER)
//Tooltip //Tooltip
val tooltip = new Tooltip() val tooltip = new Tooltip()

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 javafx.geometry.Insets import javafx.geometry.Insets
import javafx.scene.layout.TilePane
import com.sothr.imagetools.engine.util.PropertiesService import com.sothr.imagetools.engine.util.PropertiesService
import grizzled.slf4j.Logging import grizzled.slf4j.Logging
@ -12,9 +13,9 @@ import grizzled.slf4j.Logging
*/ */
object ImageTileFactory extends 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 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 //set padding
imageTile.setPadding(new Insets(2, 2, 2, 2)) imageTile.setPadding(new Insets(2, 2, 2, 2))

46
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 java.util
import javafx.collections.{ModifiableObservableListBase, ObservableList} import javafx.collections.{ModifiableObservableListBase, ObservableList}
import javafx.scene.control.MultipleSelectionModel 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 * Custom Tile Pane with a multi selection model
@ -12,6 +13,14 @@ import javafx.scene.layout.TilePane
*/ */
class ImageTilePane extends TilePane { class ImageTilePane extends TilePane {
val selectionModel = new ImageTilePaneSelectionModel(this) 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 = { override def selectIndices(index: Int, indices: Int*): Unit = {
clearSelectionFormatting
this.selectedIndexes.clear() this.selectedIndexes.clear()
setSelectionFormatting(index)
this.selectedIndexes.add(index) this.selectedIndexes.add(index)
for (i <- indices) { for (i <- indices) {
setSelectionFormatting(i)
this.selectedIndexes.add(i) this.selectedIndexes.add(i)
} }
} }
override def selectAll(): Unit = { override def selectAll(): Unit = {
clearSelectionFormatting
this.selectedIndexes.clear() this.selectedIndexes.clear()
for (index <- 0 until this.parentTilePane.getChildren.size()) { for (index <- 0 until this.parentTilePane.getChildren.size()) {
setSelectionFormatting(index)
this.selectedIndexes.add(index) this.selectedIndexes.add(index)
} }
} }
override def selectFirst(): Unit = { override def selectFirst(): Unit = {
clearSelectionFormatting
this.selectedIndexes.clear() this.selectedIndexes.clear()
setSelectionFormatting(0)
this.selectedIndexes.add(0) this.selectedIndexes.add(0)
} }
override def selectLast(): Unit = { override def selectLast(): Unit = {
clearSelectionFormatting
this.selectedIndexes.clear() this.selectedIndexes.clear()
setSelectionFormatting(this.parentTilePane.getChildren.size()-1)
this.selectedIndexes.add(this.parentTilePane.getChildren.size()-1) this.selectedIndexes.add(this.parentTilePane.getChildren.size()-1)
} }
override def clearAndSelect(index: Int): Unit = { override def clearAndSelect(index: Int): Unit = {
clearSelectionFormatting
this.selectedIndexes.clear() this.selectedIndexes.clear()
setSelectionFormatting(index)
this.selectedIndexes.add(index) this.selectedIndexes.add(index)
} }
@ -70,6 +90,7 @@ class ImageTilePaneSelectionModel[ImageTile](parentTilePane: ImageTilePane) exte
} }
override def clearSelection(): Unit = { override def clearSelection(): Unit = {
clearSelectionFormatting
this.selectedIndexes.clear() this.selectedIndexes.clear()
} }
@ -90,13 +111,15 @@ class ImageTilePaneSelectionModel[ImageTile](parentTilePane: ImageTilePane) exte
} }
override def select(index: Int): Unit = { override def select(index: Int): Unit = {
this.selectedIndexes.clear()
setSelectionFormatting(index)
this.selectedIndexes.add(index) this.selectedIndexes.add(index)
} }
override def select(obj: ImageTile): Unit = { override def select(obj: ImageTile): Unit = {
if (this.parentTilePane.getChildren.contains(obj)) { if (this.parentTilePane.getChildren.contains(obj)) {
clearSelectionFormatting
this.selectedIndexes.clear() this.selectedIndexes.clear()
setSelectionFormatting(obj)
this.selectedIndexes.add(this.parentTilePane.getChildren.indexOf(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 = { override def isSelected(index: Int): Boolean = {
this.selectedIndexes.contains(index) 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] { class ArrayObservableList[E] extends ModifiableObservableListBase[E] {

8
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.setMaxWidth(this.imageTilePane.getMaxWidth)
newImageTilePane.setPrefColumns(this.imageTilePane.getPrefColumns) newImageTilePane.setPrefColumns(this.imageTilePane.getPrefColumns)
newImageTilePane.setPrefRows(this.imageTilePane.getPrefRows) 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) newImageTilePane.setTileAlignment(this.imageTilePane.getTileAlignment)
this.scrollPane.setContent(newImageTilePane) this.scrollPane.setContent(newImageTilePane)
this.imageTilePane = newImageTilePane this.imageTilePane = newImageTilePane
@ -219,7 +219,7 @@ class AppController extends Logging {
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 tempImages += similarImage.rootImage
imageTilePane.getChildren.add(ImageTileFactory.get(similarImage.rootImage))
imageTilePane.getChildren.add(ImageTileFactory.get(similarImage.rootImage, imageTilePane))
similarImage.similarImages.foreach(image => tempImages += image) similarImage.similarImages.foreach(image => tempImages += image)
} }
setPagesContent(tempImages.toList) setPagesContent(tempImages.toList)
@ -259,7 +259,7 @@ class AppController extends Logging {
override def run() { override def run() {
for (image <- images) { for (image <- images) {
debug(s"Adding image ${image.toString} to app") debug(s"Adding image ${image.toString} to app")
imageTilePane.getChildren.add(ImageTileFactory.get(image))
imageTilePane.getChildren.add(ImageTileFactory.get(image, imageTilePane))
} }
} }
}) })

Loading…
Cancel
Save