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.

234 lines
7.3 KiB

  1. package com.sothr.imagetools.ui.controller
  2. import java.io.{File, IOException}
  3. import java.util
  4. import java.util.Scanner
  5. import javafx.event.ActionEvent
  6. import javafx.fxml.FXML
  7. import javafx.scene.text.{Text, TextAlignment}
  8. import javafx.scene.web.WebView
  9. import javafx.scene.{Group, Node, Scene}
  10. import javafx.stage.{DirectoryChooser, Stage, StageStyle}
  11. import com.sothr.imagetools.engine.{ConcurrentEngine, Engine}
  12. import com.sothr.imagetools.ui.component.ImageTileFactory
  13. import com.sothr.imagetools.util.{PropertiesService, ResourceLoader}
  14. import grizzled.slf4j.Logging
  15. import org.markdown4j.Markdown4jProcessor
  16. /**
  17. * Main Application controller
  18. *
  19. * Created by drew on 12/31/13.
  20. */
  21. class AppController extends Logging {
  22. //Define controls
  23. @FXML var rootPane : javafx.scene.layout.AnchorPane = null
  24. @FXML var rootMenuBar : javafx.scene.control.MenuBar = null
  25. @FXML var imageTilePane : javafx.scene.layout.TilePane = null
  26. @FXML var tagListView : javafx.scene.control.ListView[String] = null
  27. // Labels
  28. @FXML var selectedDirectoryLabel: javafx.scene.control.Label = null
  29. // Engine
  30. val engine:Engine = new ConcurrentEngine()
  31. // Current State
  32. var currentDirectory:String = "."
  33. @FXML def initialize() = {
  34. if (PropertiesService.has("lastPath")) {
  35. currentDirectory = PropertiesService.get("lastPath", ".")
  36. selectedDirectoryLabel.setText(PropertiesService.get("lastPath", ""))
  37. }
  38. //test
  39. //val testImage = new Image()
  40. //testImage.setThumbnailPath("test.jpg")
  41. //testImage.setImagePath("test.jpg")
  42. //for (i <- 1 to 100) {
  43. // imageTilePane.getChildren.add(ImageTileFactory.get(testImage))
  44. //}
  45. //val list = FXCollections.observableArrayList[String]()
  46. //for (i <- 1 to 100) {
  47. // list.add(s"test-item ${i}")
  48. //}
  49. //tagListView.setItems(list)
  50. }
  51. //region MenuItem Actions
  52. @FXML
  53. def helpAction(event:ActionEvent) = {
  54. showExternalHTMLUtilityDialog("http://www.sothr.com")
  55. }
  56. @FXML
  57. def aboutAction(event:ActionEvent) = {
  58. debug("Displaying about screen")
  59. var aboutMessage = "Simple About Message"
  60. try {
  61. val scanner = new Scanner(ResourceLoader.get().getResourceStream("documents/about.md"))
  62. aboutMessage = ""
  63. while (scanner.hasNextLine) {
  64. aboutMessage += scanner.nextLine().trim() + "\n"
  65. }
  66. debug(s"Parsed About Message: '$aboutMessage'")
  67. } catch {
  68. case ioe:IOException =>
  69. error("Unable to read about file")
  70. }
  71. showMarkdownUtilityDialog("About", aboutMessage, 400.0, 300.0)
  72. debug("Showing About Dialog")
  73. }
  74. @FXML
  75. def closeAction(event:ActionEvent) = {
  76. debug("Closing application from the menu bar")
  77. val stage:Stage = this.rootMenuBar.getScene.getWindow.asInstanceOf[Stage]
  78. stage.close()
  79. }
  80. @FXML
  81. def browseFolders(event:ActionEvent) = {
  82. val chooser = new DirectoryChooser()
  83. chooser.setTitle("ImageTools Browser")
  84. val defaultDirectory = new File(currentDirectory)
  85. chooser.setInitialDirectory(defaultDirectory)
  86. val window = this.rootPane.getScene.getWindow
  87. val selectedDirectory = chooser.showDialog(window)
  88. info(s"Selected Directory: ${selectedDirectory.getAbsolutePath}")
  89. selectedDirectoryLabel.setText(selectedDirectory.getAbsolutePath)
  90. currentDirectory = selectedDirectory.getAbsolutePath
  91. PropertiesService.set("lastPath",selectedDirectory.getAbsolutePath)
  92. }
  93. @FXML
  94. def showAllImages(event:ActionEvent) = {
  95. imageTilePane.getChildren.setAll(new util.ArrayList[Node]())
  96. val images = engine.getImagesForDirectory(currentDirectory)
  97. info(s"Displaying ${images.length} images")
  98. for (image <- images) {
  99. debug(s"Adding image ${image.toString} to app")
  100. imageTilePane.getChildren.add(ImageTileFactory.get(image))
  101. }
  102. }
  103. @FXML
  104. def showSimilarImages(event:ActionEvent) = {
  105. imageTilePane.getChildren.setAll(new util.ArrayList[Node]())
  106. val similarImages = engine.getSimilarImagesForDirectory(currentDirectory)
  107. info(s"Displaying ${similarImages.length} similar images")
  108. for (similarImage <- similarImages) {
  109. debug(s"Adding similar images ${similarImage.rootImage.toString} to app")
  110. imageTilePane.getChildren.add(ImageTileFactory.get(similarImage.rootImage))
  111. similarImage.similarImages.foreach( image => imageTilePane.getChildren.add(ImageTileFactory.get(image)))
  112. }
  113. }
  114. //endregion
  115. //todo: include a templating engine for rendering information
  116. //todo: show a dialog that is rendered from markdown content
  117. def showMarkdownUtilityDialog(title:String, markdown:String, width:Double = 800.0, height:Double = 600.0) = {
  118. val htmlBody = new Markdown4jProcessor().process(markdown)
  119. showHTMLUtilityDialog(title, htmlBody, width, height)
  120. }
  121. /**
  122. * Render HTML content to a utility dialog. No input or output, just raw rendered content through a webkit engine.
  123. *
  124. * @param title Title of the dialog
  125. * @param htmlBody Body to render
  126. * @param width Desired width of the dialog
  127. * @param height Desired height of the dialog
  128. */
  129. def showHTMLUtilityDialog(title:String, htmlBody:String, width:Double = 800.0, height:Double = 600.0) = {
  130. val dialog:Stage = new Stage()
  131. dialog.initStyle(StageStyle.UTILITY)
  132. val parent:Group = new Group()
  133. //setup the HTML view
  134. val htmlView = new WebView
  135. htmlView.getEngine.loadContent(htmlBody)
  136. htmlView.setMinWidth(width)
  137. htmlView.setMinHeight(height)
  138. htmlView.setPrefWidth(width)
  139. htmlView.setPrefHeight(height)
  140. parent.getChildren.add(htmlView)
  141. val scene:Scene = new Scene(parent)
  142. dialog.setScene(scene)
  143. dialog.setResizable(false)
  144. dialog.setTitle(title)
  145. dialog.show()
  146. }
  147. def showExternalHTMLUtilityDialog(url:String) = {
  148. val dialog:Stage = new Stage()
  149. dialog.initStyle(StageStyle.UTILITY)
  150. val parent:Group = new Group()
  151. //setup the HTML view
  152. val htmlView = new WebView
  153. htmlView.getEngine.load(url)
  154. //htmlView.setMinWidth(width)
  155. //htmlView.setMinHeight(height)
  156. //htmlView.setPrefWidth(width)
  157. //htmlView.setPrefHeight(height)
  158. parent.getChildren.add(htmlView)
  159. val scene:Scene = new Scene(parent)
  160. dialog.setScene(scene)
  161. dialog.setResizable(false)
  162. dialog.setTitle(htmlView.getEngine.getTitle)
  163. dialog.show()
  164. }
  165. /**
  166. * Show a plain text utility dialog
  167. *
  168. * @param message Message to display
  169. * @param wrapWidth When to wrap
  170. * @param alignment How it should be aligned
  171. */
  172. def showUtilityDialog(title:String,
  173. message:String,
  174. wrapWidth:Double=300.0,
  175. xOffset:Double = 25.0,
  176. yOffset:Double = 25.0,
  177. alignment:TextAlignment=TextAlignment.JUSTIFY) = {
  178. val dialog:Stage = new Stage()
  179. dialog.initStyle(StageStyle.UTILITY)
  180. val parent:Group = new Group()
  181. // fill the text box
  182. val messageText = new Text()
  183. messageText.setText(message)
  184. messageText.setWrappingWidth(wrapWidth)
  185. messageText.setX(xOffset)
  186. messageText.setY(yOffset)
  187. messageText.setTextAlignment(TextAlignment.JUSTIFY)
  188. parent.getChildren.add(messageText)
  189. val scene:Scene = new Scene(parent)
  190. dialog.setScene(scene)
  191. dialog.setResizable(false)
  192. dialog.setMinWidth(wrapWidth+xOffset*2)
  193. dialog.setTitle(title)
  194. dialog.show()
  195. }
  196. def print():String = {
  197. "This method works"
  198. }
  199. }