You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

245 lines
7.1 KiB

  1. package com.sothr.imagetools.ui.component
  2. import java.util
  3. import javafx.collections.{ModifiableObservableListBase, ObservableList}
  4. import javafx.event.{ActionEvent, EventHandler}
  5. import javafx.geometry.Side
  6. import javafx.scene.control.{MenuItem, ContextMenu, MultipleSelectionModel}
  7. import javafx.scene.input.ContextMenuEvent
  8. import javafx.scene.layout._
  9. import javafx.scene.paint.Color
  10. import javafx.scene.Node
  11. import grizzled.slf4j.Logging
  12. /**
  13. * Custom Tile Pane with a multi selection model
  14. *
  15. * Created by drew on 8/29/14.
  16. */
  17. class ImageTilePane extends TilePane with Logging {
  18. val selectionModel = new ImageTilePaneSelectionModel(this)
  19. //this.setOnContextMenuRequested(new EventHandler[ContextMenuEvent] {
  20. // override def handle(event: ContextMenuEvent): Unit = {
  21. // handleContextMenu(event)
  22. // }
  23. //})
  24. def handleContextMenu(event: ContextMenuEvent) = {
  25. //Build and show a context menu
  26. debug("Context Menu Request Received")
  27. val numSelected = this.selectionModel.getSelectedIndices.size()
  28. if (numSelected > 0) {
  29. if (numSelected == 1) {
  30. val contextMenu = getSingleSelectionContextMenu
  31. debug("Showing context menu")
  32. contextMenu.show(event.getTarget.asInstanceOf[Node],Side.RIGHT,0d,0d)
  33. } else {
  34. val contextMenu = getMulipleSelectionContextMenu
  35. debug("Showing context menu")
  36. contextMenu.show(event.getTarget.asInstanceOf[Node],Side.RIGHT,0d,0d)
  37. }
  38. }
  39. }
  40. def getSingleSelectionContextMenu : ContextMenu = {
  41. debug("Building single-selection context menu")
  42. val contextMenu = new ContextMenu()
  43. val item1 = new MenuItem("Single Selection")
  44. item1.setOnAction(new EventHandler[ActionEvent]() {
  45. def handle(e: ActionEvent) = {
  46. debug("Single Selection")
  47. }
  48. })
  49. val item2 = new MenuItem("BlahBlah")
  50. item2.setOnAction(new EventHandler[ActionEvent]() {
  51. def handle(e: ActionEvent) = {
  52. debug("BlahBlah")
  53. }
  54. })
  55. contextMenu.getItems.addAll(item1, item2)
  56. contextMenu
  57. }
  58. def getMulipleSelectionContextMenu : ContextMenu = {
  59. debug("Building multi-selection context menu")
  60. val contextMenu = new ContextMenu()
  61. val item1 = new MenuItem("Multi Selection")
  62. item1.setOnAction(new EventHandler[ActionEvent]() {
  63. def handle(e: ActionEvent) = {
  64. debug("Multi Selection")
  65. }
  66. })
  67. val item2 = new MenuItem("BlahBlah")
  68. item2.setOnAction(new EventHandler[ActionEvent]() {
  69. def handle(e: ActionEvent) = {
  70. debug("BlahBlah")
  71. }
  72. })
  73. contextMenu.getItems.addAll(item1, item2)
  74. contextMenu
  75. }
  76. def imageSelected(imageTile: ImageTile) = {
  77. this.selectionModel.clearAndSelect(this.getChildren.indexOf(imageTile))
  78. }
  79. def addImageSelected(imageTile: ImageTile) = {
  80. this.selectionModel.select(this.getChildren.indexOf(imageTile))
  81. }
  82. }
  83. /**
  84. * Multiple selection model for ImageTilePane
  85. *
  86. */
  87. class ImageTilePaneSelectionModel[ImageTile](parentTilePane: ImageTilePane) extends MultipleSelectionModel[ImageTile] {
  88. val selectedIndexes: ObservableList[Integer] = new ArrayObservableList[Integer]()
  89. override def getSelectedIndices: ObservableList[Integer] = {
  90. this.selectedIndexes
  91. }
  92. override def getSelectedItems: ObservableList[ImageTile] = {
  93. val selected = new ArrayObservableList[ImageTile]()
  94. val iterator = selectedIndexes.iterator()
  95. while (iterator.hasNext) {
  96. selected.add(this.parentTilePane.getChildren.get(iterator.next()).asInstanceOf[ImageTile])
  97. }
  98. selected
  99. }
  100. override def selectIndices(index: Int, indices: Int*): Unit = {
  101. clearSelectionFormatting
  102. this.selectedIndexes.clear()
  103. setSelectionFormatting(index)
  104. this.selectedIndexes.add(index)
  105. for (i <- indices) {
  106. setSelectionFormatting(i)
  107. this.selectedIndexes.add(i)
  108. }
  109. }
  110. override def selectAll(): Unit = {
  111. clearSelectionFormatting
  112. this.selectedIndexes.clear()
  113. for (index <- 0 until this.parentTilePane.getChildren.size()) {
  114. setSelectionFormatting(index)
  115. this.selectedIndexes.add(index)
  116. }
  117. }
  118. override def selectFirst(): Unit = {
  119. clearSelectionFormatting
  120. this.selectedIndexes.clear()
  121. setSelectionFormatting(0)
  122. this.selectedIndexes.add(0)
  123. }
  124. override def selectLast(): Unit = {
  125. clearSelectionFormatting
  126. this.selectedIndexes.clear()
  127. setSelectionFormatting(this.parentTilePane.getChildren.size()-1)
  128. this.selectedIndexes.add(this.parentTilePane.getChildren.size()-1)
  129. }
  130. override def clearAndSelect(index: Int): Unit = {
  131. clearSelectionFormatting
  132. this.selectedIndexes.clear()
  133. setSelectionFormatting(index)
  134. this.selectedIndexes.add(index)
  135. }
  136. override def clearSelection(index: Int): Unit = {
  137. this.selectedIndexes.remove(index)
  138. }
  139. override def clearSelection(): Unit = {
  140. clearSelectionFormatting
  141. this.selectedIndexes.clear()
  142. }
  143. override def selectPrevious(): Unit = {
  144. if (this.selectedIndexes.size == 1) {
  145. val currentIndex = this.selectedIndexes.get(0)
  146. val nextIndex = if (currentIndex < 1) 0 else currentIndex - 1
  147. this.selectedIndexes.set(0, nextIndex)
  148. }
  149. }
  150. override def selectNext(): Unit = {
  151. if (this.selectedIndexes.size == 1) {
  152. val currentIndex = this.selectedIndexes.get(0)
  153. val nextIndex = if (currentIndex >= this.parentTilePane.getChildren.size-1) this.parentTilePane.getChildren.size-1 else currentIndex + 1
  154. this.selectedIndexes.set(0, nextIndex)
  155. }
  156. }
  157. override def select(index: Int): Unit = {
  158. setSelectionFormatting(index)
  159. this.selectedIndexes.add(index)
  160. }
  161. override def select(obj: ImageTile): Unit = {
  162. if (this.parentTilePane.getChildren.contains(obj)) {
  163. clearSelectionFormatting
  164. this.selectedIndexes.clear()
  165. setSelectionFormatting(obj)
  166. this.selectedIndexes.add(this.parentTilePane.getChildren.indexOf(obj))
  167. }
  168. }
  169. override def isEmpty: Boolean = {
  170. this.parentTilePane.getChildren.isEmpty
  171. }
  172. override def isSelected(index: Int): Boolean = {
  173. this.selectedIndexes.contains(index)
  174. }
  175. private def clearSelectionFormatting() = {
  176. val iterator = this.parentTilePane.getChildren.iterator()
  177. while (iterator.hasNext) {
  178. //remove the selection styling
  179. val imageTile: VBox = iterator.next().asInstanceOf[VBox]
  180. imageTile.setBorder(Border.EMPTY)
  181. }
  182. }
  183. private def setSelectionFormatting(index: Int): Unit = {
  184. setSelectionFormatting(this.parentTilePane.getChildren.get(index).asInstanceOf[ImageTile])
  185. }
  186. private def setSelectionFormatting(imageTile: ImageTile): Unit = {
  187. val borderStroke = new BorderStroke(Color.BLUE, BorderStrokeStyle.SOLID, CornerRadii.EMPTY,BorderStroke.THIN)
  188. imageTile.asInstanceOf[VBox].setBorder(new Border(borderStroke))
  189. }
  190. }
  191. class ArrayObservableList[E] extends ModifiableObservableListBase[E] {
  192. val delegate: util.ArrayList[E] = new util.ArrayList[E]()
  193. def get(index: Int): E = {
  194. delegate.get(index)
  195. }
  196. def size = {
  197. delegate.size
  198. }
  199. def doAdd (index: Int, element: E) = {
  200. delegate.add(index, element)
  201. }
  202. def doSet (index: Int, element: E): E = {
  203. delegate.set(index, element)
  204. }
  205. def doRemove (index: Int): E = {
  206. delegate.remove(index)
  207. }
  208. }