315 lines
11 KiB
Kotlin
315 lines
11 KiB
Kotlin
package org.hso.texturesyncclient.controller
|
|
|
|
import javafx.application.Platform
|
|
import javafx.collections.ObservableList
|
|
import javafx.event.EventHandler
|
|
import javafx.scene.image.Image
|
|
import javafx.stage.DirectoryChooser
|
|
import org.hso.texturesyncclient.alerts.JFXInfoAlert
|
|
import org.hso.texturesyncclient.alerts.JFXOkayCancelAlert
|
|
import org.hso.texturesyncclient.controller.net.AutoConnect
|
|
import org.hso.texturesyncclient.controller.net.Connection
|
|
import org.hso.texturesyncclient.model.GUIModel
|
|
import org.hso.texturesyncclient.model.Sha256
|
|
import org.hso.texturesyncclient.model.Texture
|
|
import org.hso.texturesyncclient.model.TextureFormat
|
|
import org.hso.texturesyncclient.view.importView.ImportView
|
|
import org.hso.texturesyncclient.view.mainView.MainView
|
|
import org.hso.texturesyncclient.view.mainView.MainViewController
|
|
import org.hso.texturesyncclient.view.startupView.StartupView
|
|
import org.hso.texturesyncclient.view.startupView.StartupViewController
|
|
import tornadofx.Controller
|
|
import tornadofx.find
|
|
import tornadofx.observable
|
|
import java.io.File
|
|
import java.io.FileOutputStream
|
|
import java.io.IOException
|
|
import java.net.InetAddress
|
|
import java.nio.file.Files
|
|
import java.text.SimpleDateFormat
|
|
import java.util.*
|
|
import javax.imageio.ImageIO
|
|
|
|
class RootController : Controller() {
|
|
|
|
private val mvc: MainViewController by inject()
|
|
private val svc: StartupViewController by inject()
|
|
|
|
private lateinit var con: Connection
|
|
private lateinit var selectedTextureModel: GUIModel
|
|
private var lastExportDir: String = System.getProperty("user.home")
|
|
|
|
/**
|
|
* 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>) {
|
|
val data = Files.readAllBytes(File(path).toPath()) // this is the image as byte array
|
|
|
|
val uuid = UUID.randomUUID()
|
|
val format = if (File(path).extension.toLowerCase() == "png") TextureFormat.PNG else TextureFormat.JPEG
|
|
val bimg = ImageIO.read(File(path)) //image for obtaining resolution
|
|
val resolution = Pair(bimg.height, bimg.width)
|
|
val cal = Calendar.getInstance() //calendar obj with current time
|
|
val hash = Sha256(data)
|
|
|
|
|
|
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;"
|
|
)
|
|
|
|
|
|
val newTexture = Texture(uuid, name, tags.toTypedArray(), format, resolution, cal, hash)
|
|
|
|
try {
|
|
con.uploadTexture(newTexture, data)
|
|
println("Texture upload successful")
|
|
} catch (e: IllegalArgumentException) {
|
|
println(e)
|
|
alertImportHash.showAndWait()
|
|
} catch (e: Exception) {
|
|
alertImport.showAndWait()
|
|
println(e)
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Initialize connection to server and switch to MainView if connected
|
|
* @param name server name as IP or domain
|
|
*/
|
|
fun initConnection(name: String) {
|
|
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()
|
|
println("[auto] Connection to Server successful")
|
|
switchStartupToMain()
|
|
showAll()
|
|
} else {
|
|
println("[auto] no server found")
|
|
}
|
|
} catch (e: Exception) {
|
|
println(e)
|
|
println("[auto] Connection to Server NOT successful")
|
|
}
|
|
if (SettingsController.serverAddressIsSet()) {
|
|
println("[file] try connect with settings file")
|
|
try {
|
|
svc.setServerAddress(SettingsController.getServerAddress()) // FIXME this crashes the client when there is either not text or no label!
|
|
con = Connection(InetAddress.getByName(SettingsController.getServerAddress()))
|
|
con.ping()
|
|
println("[file] Connection to Server successful")
|
|
switchStartupToMain()
|
|
showAll()
|
|
} catch (e: Exception) {
|
|
println(e)
|
|
println("[file] Connection to Server NOT successful")
|
|
}
|
|
} else {
|
|
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()
|
|
showAll()
|
|
println("swithing to MainView @ initCon")
|
|
} catch (e: Exception) {
|
|
println(e)
|
|
println("Connection to Server NOT successful")
|
|
|
|
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()
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
fun queryElements(tags: ObservableList<String>): ArrayList<GUIModel> {
|
|
mvc.setVisibleMetaTags(false)
|
|
val previewList = arrayListOf<GUIModel>()
|
|
|
|
try {
|
|
con.query(tags.toTypedArray()).forEach {
|
|
runAsync {
|
|
Platform.runLater {
|
|
mvc.addElement(GUIModel(it, con.getTexturePreview(it.textureHash)))
|
|
}
|
|
}
|
|
}
|
|
} catch (e: Exception) {
|
|
println(e)
|
|
}
|
|
|
|
println(previewList.size)
|
|
|
|
return previewList
|
|
}
|
|
|
|
/**
|
|
* save the texture file to a local directory
|
|
* @param data the texture as meta element
|
|
*/
|
|
fun exportTexture(data: Texture) {
|
|
val directoryChooser = DirectoryChooser()
|
|
directoryChooser.title = "Export Verzeichnis wählen"
|
|
directoryChooser.initialDirectory = File(lastExportDir)
|
|
|
|
|
|
val alertExport = JFXInfoAlert(
|
|
"Exporterien fehlgeschlagen",
|
|
"Mögliche Ursachen:" +
|
|
"\n- Datei existiert bereits" +
|
|
"\n- Ordner nicht beschreibbar",
|
|
"-fx-button-type: RAISED; -fx-background-color: #2b7bbb; -fx-text-fill: #000000;"
|
|
)
|
|
|
|
val dir = directoryChooser.showDialog(primaryStage)
|
|
if (dir != null) {
|
|
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
|
|
|
|
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()
|
|
}
|
|
}
|
|
lastExportDir = dir.absolutePath //store last user chosen dir
|
|
}
|
|
}
|
|
|
|
/**
|
|
* show the detailed meta information in the DetailView
|
|
* @param data the texture as meta element
|
|
*/
|
|
fun showDetail(data: Texture) {
|
|
mvc.setPreview3DTexture(con.getTexturePreview(data.textureHash))
|
|
val sdf = SimpleDateFormat("dd.MM.yyyy")
|
|
|
|
mvc.setMeta(
|
|
data.name,
|
|
"${data.resolution.first}px x ${data.resolution.second}px",
|
|
data.format.toString(),
|
|
sdf.format(data.addedOn.time)
|
|
)
|
|
mvc.setTags(data.tags.toList().observable())
|
|
mvc.setVisibleMetaTags(true)
|
|
}
|
|
|
|
/**
|
|
* remove a texture from the FolderView and the server
|
|
*/
|
|
fun deleteTexture() {
|
|
val dialogDelete = JFXOkayCancelAlert(
|
|
"Löschen",
|
|
"Textur ${selectedTextureModel.data.name} wirklich löschen?",
|
|
"-fx-button-type: RAISED; -fx-background-color: #2b7bbb; -fx-text-fill: #000000;"
|
|
)
|
|
dialogDelete.okayAction = EventHandler {
|
|
con.deleteTexture(selectedTextureModel.data)
|
|
mvc.removeTextureFromView(selectedTextureModel.data)
|
|
// reset the DetailView
|
|
mvc.setVisibleMetaTags(false)
|
|
mvc.setPreview3DTexture(Image("icons/TextureSync_Icon_256x256.jpeg"))
|
|
}
|
|
dialogDelete.cancelAction = EventHandler {
|
|
// Do nothing
|
|
}
|
|
dialogDelete.showAndWait()
|
|
}
|
|
|
|
fun updateTexture(name: String, tags: Array<String>) {
|
|
val newTexture = selectedTextureModel.data.copy(
|
|
tags = tags,
|
|
name = name
|
|
)
|
|
try {
|
|
con.updateTexture(
|
|
selectedTextureModel.data,
|
|
newTexture,
|
|
con.getTextureFile(selectedTextureModel.data.textureHash)
|
|
)
|
|
selectedTextureModel.data = newTexture
|
|
} catch (e: Exception) {
|
|
println(e)
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* show all available textures at start
|
|
*/
|
|
private fun showAll() {
|
|
queryElements(mvc.getTags())
|
|
}
|
|
|
|
/**
|
|
* set the last selected texture-GUIModell
|
|
* @param model the last selected element
|
|
*/
|
|
fun setSelectedTexture(model: GUIModel) {
|
|
selectedTextureModel = model
|
|
selectedTexture = model.data
|
|
}
|
|
|
|
companion object {
|
|
|
|
var selectedTexture: Texture? = null
|
|
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
} |