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

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  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.util.{PropertiesService, ResourceLoader}
  12. import com.sothr.imagetools.engine.{ConcurrentEngine, Engine}
  13. import com.sothr.imagetools.ui.component.ImageTileFactory
  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. }