2019-04-30 16:49:02 +02:00
package org.hso.texturesyncclient.controller
2019-06-05 16:05:10 +02:00
import javafx.application.Platform
2019-06-03 17:33:23 +02:00
import javafx.collections.ObservableList
2019-06-06 14:41:30 +02:00
import javafx.event.EventHandler
2019-06-13 21:43:43 +02:00
import javafx.scene.image.Image
2019-06-04 18:20:09 +02:00
import javafx.stage.DirectoryChooser
2019-06-08 14:01:49 +02:00
import org.hso.texturesyncclient.alerts.JFXInfoAlert
2019-06-06 14:41:30 +02:00
import org.hso.texturesyncclient.alerts.JFXOkayCancelAlert
2019-06-07 09:52:09 +02:00
import org.hso.texturesyncclient.controller.net.AutoConnect
2019-06-03 16:46:57 +02:00
import org.hso.texturesyncclient.controller.net.Connection
2019-06-04 18:20:09 +02:00
import org.hso.texturesyncclient.model.GUIModel
2019-06-04 14:57:54 +02:00
import org.hso.texturesyncclient.model.Sha256
import org.hso.texturesyncclient.model.Texture
import org.hso.texturesyncclient.model.TextureFormat
2019-06-05 16:23:45 +02:00
import org.hso.texturesyncclient.view.importView.ImportView
2019-06-04 16:05:47 +02:00
import org.hso.texturesyncclient.view.mainView.MainView
2019-06-03 15:29:01 +02:00
import org.hso.texturesyncclient.view.mainView.MainViewController
2019-06-04 16:05:47 +02:00
import org.hso.texturesyncclient.view.startupView.StartupView
2019-06-03 16:46:57 +02:00
import org.hso.texturesyncclient.view.startupView.StartupViewController
2019-06-03 15:29:01 +02:00
import tornadofx.Controller
2019-06-09 13:38:11 +02:00
import tornadofx.find
2019-06-04 18:20:09 +02:00
import tornadofx.observable
2019-06-03 21:40:02 +02:00
import java.io.File
2019-06-05 22:07:03 +02:00
import java.io.FileOutputStream
2019-06-08 14:01:49 +02:00
import java.io.IOException
2019-06-12 18:57:42 +02:00
import java.net.InetAddress
import java.nio.file.Files
2019-06-08 13:31:29 +02:00
import java.text.SimpleDateFormat
2019-06-12 18:57:42 +02:00
import java.util.*
import javax.imageio.ImageIO
2019-06-08 13:31:29 +02:00
2019-06-03 17:33:23 +02:00
class RootController : Controller ( ) {
2019-04-30 16:49:02 +02:00
2019-06-03 15:29:01 +02:00
private val mvc : MainViewController by inject ( )
2019-06-03 16:46:57 +02:00
private val svc : StartupViewController by inject ( )
2019-06-03 15:29:01 +02:00
2019-06-04 16:05:47 +02:00
private lateinit var con : Connection
2019-06-10 14:05:56 +02:00
private lateinit var selectedTextureModel : GUIModel
2019-06-05 22:07:03 +02:00
private var lastExportDir : String = System . getProperty ( " user.home " )
2019-06-05 16:05:10 +02:00
2019-06-03 17:33:23 +02:00
/ * *
* calculate the resolution , get today ' s date -> upload to server
* @param path the absolute path of the file on the client ' s system
* @param name the file name
* @param tags all tags for the file
* /
fun importTexture ( path : String , name : String , tags : ObservableList < String > ) {
2019-06-09 13:29:07 +02:00
val data = Files . readAllBytes ( File ( path ) . toPath ( ) ) // this is the image as byte array
2019-06-03 17:33:23 +02:00
2019-06-04 14:57:54 +02:00
val uuid = UUID . randomUUID ( )
val format = if ( File ( path ) . extension . toLowerCase ( ) == " png " ) TextureFormat . PNG else TextureFormat . JPEG
2019-06-13 21:22:42 +02:00
val bimg = ImageIO . read ( File ( path ) ) //image for obtaining resolution
2019-06-14 11:18:58 +02:00
val resolution = Pair ( bimg . width , bimg . height )
2019-06-04 14:57:54 +02:00
val cal = Calendar . getInstance ( ) //calendar obj with current time
2019-06-05 16:05:10 +02:00
val hash = Sha256 ( data )
2019-06-04 14:57:54 +02:00
2019-06-08 14:20:48 +02:00
val alertImportHash = JFXInfoAlert (
" Upload fehlgeschlagen " ,
" Die Textur wurde nicht fehlerfrei übertragen " ,
" -fx-button-type: RAISED; -fx-background-color: #2b7bbb; -fx-text-fill: #000000; "
)
val alertImport = JFXInfoAlert (
" Upload fehlgeschlagen " ,
" Mögliche Ursachen: " +
" \n - Textur existiert bereits " +
" \n - Server nicht bereit " ,
" -fx-button-type: RAISED; -fx-background-color: #2b7bbb; -fx-text-fill: #000000; "
)
2019-06-03 20:42:28 +02:00
2019-06-04 14:57:54 +02:00
val newTexture = Texture ( uuid , name , tags . toTypedArray ( ) , format , resolution , cal , hash )
2019-06-03 20:42:28 +02:00
2019-06-04 16:05:47 +02:00
try {
con . uploadTexture ( newTexture , data )
println ( " Texture upload successful " )
2019-06-08 14:20:48 +02:00
} catch ( e : IllegalArgumentException ) {
2019-06-04 16:05:47 +02:00
println ( e )
2019-06-08 14:20:48 +02:00
alertImportHash . showAndWait ( )
} catch ( e : Exception ) {
alertImport . showAndWait ( )
2019-06-09 13:29:07 +02:00
println ( e )
2019-06-04 16:05:47 +02:00
}
2019-06-09 13:29:07 +02:00
2019-06-04 16:05:47 +02:00
}
/ * *
2019-06-05 16:05:10 +02:00
* Initialize connection to server and switch to MainView if connected
2019-06-04 16:05:47 +02:00
* @param name server name as IP or domain
* /
fun initConnection ( name : String ) {
2019-06-07 09:52:09 +02:00
if ( name == " " ) {
//no user input, try automatic connect or restore address from settings file
println ( " try auto connect " )
try {
val foundServer = AutoConnect . searchServer ( )
if ( foundServer != null ) {
println ( " [auto] server found " )
con = foundServer
con . ping ( )
2019-06-13 21:52:26 +02:00
println ( " [auto] Connection to Server successful " )
2019-06-07 09:52:09 +02:00
switchStartupToMain ( )
2019-06-08 21:59:09 +02:00
showAll ( )
2019-06-14 11:28:43 +02:00
return // abort
2019-06-07 09:52:09 +02:00
} else {
println ( " [auto] no server found " )
}
} catch ( e : Exception ) {
println ( e )
2019-06-13 21:52:26 +02:00
println ( " [auto] Connection to Server NOT successful " )
2019-06-07 09:52:09 +02:00
}
if ( SettingsController . serverAddressIsSet ( ) ) {
println ( " [file] try connect with settings file " )
try {
2019-06-08 13:25:55 +02:00
svc . setServerAddress ( SettingsController . getServerAddress ( ) ) // FIXME this crashes the client when there is either not text or no label!
2019-06-07 09:52:09 +02:00
con = Connection ( InetAddress . getByName ( SettingsController . getServerAddress ( ) ) )
con . ping ( )
println ( " [file] Connection to Server successful " )
switchStartupToMain ( )
2019-06-08 21:59:09 +02:00
showAll ( )
2019-06-14 11:28:43 +02:00
return // abort
2019-06-07 09:52:09 +02:00
} catch ( e : Exception ) {
println ( e )
println ( " [file] Connection to Server NOT successful " )
}
2019-06-08 12:47:34 +02:00
} else {
2019-06-07 09:52:09 +02:00
println ( " [file] no address in settings file " )
}
} else {
//try to connect with user input
try {
println ( " try connect with user input " )
con = Connection ( InetAddress . getByName ( name ) )
con . ping ( )
println ( " Connection to Server successful " )
SettingsController . setServerAddress ( name ) //store address in settings file
switchStartupToMain ( )
2019-06-08 21:59:09 +02:00
showAll ( )
2019-06-07 09:52:09 +02:00
println ( " swithing to MainView @ initCon " )
2019-06-14 11:28:43 +02:00
return // abort
2019-06-07 09:52:09 +02:00
} catch ( e : Exception ) {
println ( e )
println ( " Connection to Server NOT successful " )
2019-06-13 21:52:26 +02:00
Platform . runLater {
JFXInfoAlert (
" Verbinden fehlgeschlagen " ,
" Mögliche Ursachen: " +
" \n - der angegebene Server ist offline " +
" \n - die benötigten Ports sind nicht offen " ,
" -fx-button-type: RAISED; -fx-background-color: #2b7bbb; -fx-text-fill: #000000; "
) . showAndWait ( )
}
2019-06-07 09:52:09 +02:00
}
2019-06-04 18:20:09 +02:00
}
}
2019-06-04 16:05:47 +02:00
2019-06-07 16:19:04 +02:00
fun queryElements ( tags : ObservableList < String > ) : ArrayList < GUIModel > {
2019-06-08 22:09:43 +02:00
mvc . setVisibleMetaTags ( false )
2019-06-04 18:20:09 +02:00
val previewList = arrayListOf < GUIModel > ( )
2019-06-04 16:05:47 +02:00
2019-06-04 18:20:09 +02:00
try {
con . query ( tags . toTypedArray ( ) ) . forEach {
2019-06-07 16:19:04 +02:00
runAsync {
Platform . runLater {
mvc . addElement ( GUIModel ( it , con . getTexturePreview ( it . textureHash ) ) )
}
}
2019-06-04 18:20:09 +02:00
}
2019-06-04 16:05:47 +02:00
} catch ( e : Exception ) {
println ( e )
}
2019-06-04 18:20:09 +02:00
println ( previewList . size )
return previewList
2019-06-03 17:33:23 +02:00
}
2019-06-03 22:24:18 +02:00
2019-06-05 15:44:12 +02:00
/ * *
* save the texture file to a local directory
* @param data the texture as meta element
* /
2019-06-04 18:20:09 +02:00
fun exportTexture ( data : Texture ) {
val directoryChooser = DirectoryChooser ( )
directoryChooser . title = " Export Verzeichnis wählen "
2019-06-05 22:07:03 +02:00
directoryChooser . initialDirectory = File ( lastExportDir )
2019-06-04 18:20:09 +02:00
2019-06-08 14:01:49 +02:00
val alertExport = JFXInfoAlert (
" Exporterien fehlgeschlagen " ,
" Mögliche Ursachen: " +
2019-06-08 14:20:48 +02:00
" \n - Datei existiert bereits " +
" \n - Ordner nicht beschreibbar " ,
2019-06-08 14:01:49 +02:00
" -fx-button-type: RAISED; -fx-background-color: #2b7bbb; -fx-text-fill: #000000; "
)
2019-06-04 18:20:09 +02:00
val dir = directoryChooser . showDialog ( primaryStage )
if ( dir != null ) {
2019-06-05 22:07:03 +02:00
val extension = if ( data . format == TextureFormat . PNG ) " .png " else " .jpeg " //get file format
val filePath = " $dir / ${data.name} $extension " //build absolute exported texture path
val exportedFile = File ( filePath ) //create file
2019-06-08 14:01:49 +02:00
if ( exportedFile . exists ( ) ) {
alertExport . showAndWait ( )
} else {
try {
val fileout = FileOutputStream ( exportedFile )
fileout . write ( con . getTextureFile ( data . textureHash ) ) //write bytes in file fileout.close()
fileout . close ( )
} catch ( e : IOException ) {
alertExport . showAndWait ( )
}
}
2019-06-05 22:07:03 +02:00
lastExportDir = dir . absolutePath //store last user chosen dir
2019-06-04 18:20:09 +02:00
}
}
2019-06-07 13:48:42 +02:00
/ * *
* show the detailed meta information in the DetailView
* @param data the texture as meta element
* /
2019-06-04 18:20:09 +02:00
fun showDetail ( data : Texture ) {
mvc . setPreview3DTexture ( con . getTexturePreview ( data . textureHash ) )
2019-06-08 13:31:29 +02:00
val sdf = SimpleDateFormat ( " dd.MM.yyyy " )
2019-06-08 21:59:09 +02:00
mvc . setMeta (
data . name ,
" ${data.resolution.first} px x ${data.resolution.second} px " ,
data . format . toString ( ) ,
sdf . format ( data . addedOn . time )
)
2019-06-04 18:20:09 +02:00
mvc . setTags ( data . tags . toList ( ) . observable ( ) )
2019-06-08 22:09:43 +02:00
mvc . setVisibleMetaTags ( true )
2019-06-04 18:20:09 +02:00
}
2019-06-07 13:48:42 +02:00
/ * *
* remove a texture from the FolderView and the server
* /
2019-06-13 21:22:42 +02:00
fun deleteTexture ( ) {
2019-06-06 14:41:30 +02:00
val dialogDelete = JFXOkayCancelAlert (
" Löschen " ,
2019-06-10 14:05:56 +02:00
" Textur ${selectedTextureModel.data.name} wirklich löschen? " ,
2019-06-06 14:41:30 +02:00
" -fx-button-type: RAISED; -fx-background-color: #2b7bbb; -fx-text-fill: #000000; "
)
dialogDelete . okayAction = EventHandler {
2019-06-10 14:05:56 +02:00
con . deleteTexture ( selectedTextureModel . data )
mvc . removeTextureFromView ( selectedTextureModel . data )
2019-06-13 21:43:43 +02:00
// reset the DetailView
mvc . setVisibleMetaTags ( false )
mvc . setPreview3DTexture ( Image ( " icons/TextureSync_Icon_256x256.jpeg " ) )
2019-06-06 14:41:30 +02:00
}
dialogDelete . cancelAction = EventHandler {
2019-06-07 13:48:42 +02:00
// Do nothing
2019-06-06 14:41:30 +02:00
}
dialogDelete . showAndWait ( )
2019-06-05 22:33:37 +02:00
}
2019-06-13 00:10:00 +02:00
fun updateTexture ( name : String , tags : Array < String > ) {
val newTexture = selectedTextureModel . data . copy (
tags = tags ,
name = name
2019-06-08 12:47:34 +02:00
)
2019-06-10 14:05:56 +02:00
try {
2019-06-12 18:57:42 +02:00
con . updateTexture (
selectedTextureModel . data ,
newTexture ,
con . getTextureFile ( selectedTextureModel . data . textureHash )
)
2019-06-10 14:05:56 +02:00
selectedTextureModel . data = newTexture
} catch ( e : Exception ) {
println ( e )
}
2019-06-08 12:47:34 +02:00
}
2019-06-13 00:10:00 +02:00
2019-06-08 21:59:09 +02:00
/ * *
* show all available textures at start
* /
2019-06-09 13:38:11 +02:00
private fun showAll ( ) {
2019-06-08 21:59:09 +02:00
queryElements ( mvc . getTags ( ) )
}
2019-06-09 13:38:11 +02:00
2019-06-10 14:05:56 +02:00
/ * *
* set the last selected texture - GUIModell
* @param model the last selected element
* /
2019-06-12 18:57:42 +02:00
fun setSelectedTexture ( model : GUIModel ) {
2019-06-10 14:05:56 +02:00
selectedTextureModel = model
2019-06-13 21:22:42 +02:00
selectedTexture = model . data
2019-06-10 14:05:56 +02:00
}
2019-06-09 13:38:11 +02:00
companion object {
2019-06-13 21:22:42 +02:00
var selectedTexture : Texture ? = null
2019-06-09 13:38:11 +02:00
fun switchStartupToMain ( ) {
Platform . runLater {
find ( StartupView :: class ) . replaceWith ( MainView :: class , sizeToScene = true , centerOnScreen = true )
}
}
// These runLater calls should be unnecessary
fun switchMainToImport ( ) {
Platform . runLater {
find ( MainView :: class ) . replaceWith ( ImportView :: class , sizeToScene = true , centerOnScreen = true )
}
}
fun switchImportToMain ( ) {
Platform . runLater {
find ( ImportView :: class ) . replaceWith ( MainView :: class , sizeToScene = true , centerOnScreen = true )
}
}
}
2019-04-30 16:49:02 +02:00
}