45 Commits

Author SHA1 Message Date
8c6a43fc22 change version to 1.0 2019-06-13 22:21:41 +02:00
7f4182bfad added JFXInfoAlert if connect manually failed
closes #39
2019-06-13 21:52:26 +02:00
5fff4023f9 clear DetailVIew on delete, rename submitButton to btnSubmit, clean up 2019-06-13 21:43:43 +02:00
dfad679e6e updated planner 2019-06-13 21:36:14 +02:00
391dfe4282 don't open export if nothing is selected & clean up 2019-06-13 21:22:42 +02:00
225316abb9 Merge branch 'fix-40' of localhorst/TextureSync into master 2019-06-13 20:04:44 +02:00
f5dbcc0134 use Borderpane + Anchorpane for #40 2019-06-13 18:38:38 +02:00
cac4807357 BUG FIX: show resolution in detailview. 2019-06-13 18:37:07 +02:00
33fa741a2a fix font-color of import action btn 2019-06-13 18:35:34 +02:00
37406acd98 Fix #27 (StartupViewController is created twice) again 2019-06-13 18:04:46 +02:00
56c62422cc use blue for "Ändern" Button 2019-06-13 00:19:16 +02:00
bc43b33536 Fix #38
Note: The client architecture is broken beyond repair
2019-06-13 00:10:00 +02:00
1ac13f80d5 fix MainView ChipView TextColor 2019-06-12 22:54:30 +02:00
8dfbbae559 fix #28 2019-06-12 22:42:28 +02:00
cc03b32ade Fix #29
Redo Text of FolderView + DetailView
2019-06-12 21:05:40 +02:00
a2f5b65e30 Calling App.start(stage) early
Calling super.start early prevents a weird layouting bug
were the button of the window is white.
This could(?) be caused by stage and StartupView having
a different min-size.
2019-06-12 19:37:32 +02:00
f094a68b04 Merge branch 'resize' 2019-06-12 19:11:08 +02:00
b5545e1bae fix icon path: use png for alpha-channel 2019-06-12 19:07:29 +02:00
9a9a1e0056 Merge commit '10076fc' into resize 2019-06-12 19:03:26 +02:00
0f23749001 Merge commit '6219ad9' into resize 2019-06-12 19:03:19 +02:00
c1dbd8ffb7 Merge commit '35f8145' into resize 2019-06-12 19:03:05 +02:00
ebc6449e48 Merge commit 'e26d54e' into resize 2019-06-12 19:02:50 +02:00
bef56f978c Merge commit '9975364' into resize 2019-06-12 19:02:12 +02:00
50ea54c8d6 reformat 2019-06-12 18:57:42 +02:00
24b9755089 Merge commit '4915788' into resize 2019-06-12 18:56:37 +02:00
6fbfa050b3 Merge commit 'ee7fbae' into resize 2019-06-12 18:53:57 +02:00
9a3524143a Merge commit 'efc2845' into resize 2019-06-12 18:53:42 +02:00
10076fcef2 updated test docs 2019-06-12 14:08:23 +02:00
6219ad93d0 Fix #31 : Config Path use ~/.config instead.
This is more common for Desktop Apps.
2019-06-12 13:28:03 +02:00
8109782e4e Merge branch 'master' of git.mosad.xyz:localhorst/TextureSync 2019-06-12 13:24:26 +02:00
c2d01760c7 Set Server Version to 1.0; Show Version on Startup 2019-06-12 13:23:47 +02:00
2cac52b48d Replace logo with the new one 2019-06-12 11:38:05 +02:00
35f8145112 [kurzanleitung] added first thoughts 2019-06-10 16:05:07 +02:00
e26d54e96f added praesentation 2019-06-10 15:58:32 +02:00
7e3ce9ce56 fixed StartupViewController is created twice
closes #27
2019-06-10 15:30:00 +02:00
9975364621 updated all test documents 2019-06-10 15:19:53 +02:00
491578806e Multiple changes in the ChipView will now work for the update to server 2019-06-10 14:05:56 +02:00
b1052fa894 added shortcut ctrl+e for exporting a texture 2019-06-10 12:41:11 +02:00
36c4805061 added shortcut ctrl+i for the ImportView 2019-06-10 12:25:06 +02:00
ee7fbae29c Fix display of the month at creation date
This time on serialization as well as on deserialization
2019-06-09 16:29:37 +02:00
07f2682a2d resize ImportView too 2019-06-09 13:38:11 +02:00
efc28455c1 fixed error handling at import 2019-06-09 13:29:07 +02:00
5d223ba72b make window resizable, rework MainView code 2019-06-09 13:12:56 +02:00
15cbbb1bac fast fix for calendar bug 2019-06-09 13:03:20 +02:00
08840c4c2b Revert "Fix display of the month at creation date"
This reverts commit 19eb6660e1.
2019-06-09 13:02:26 +02:00
42 changed files with 83165 additions and 2275 deletions

View File

@ -27,7 +27,7 @@ compileTestKotlin {
} }
group 'org.hso' group 'org.hso'
version '1.0-SNAPSHOT' version '1.0'
archivesBaseName = 'TextureSync' archivesBaseName = 'TextureSync'
mainClassName = 'org.hso.texturesyncclient.app.Main' mainClassName = 'org.hso.texturesyncclient.app.Main'

View File

@ -2,25 +2,35 @@ package org.hso.texturesyncclient.app
import javafx.scene.image.Image import javafx.scene.image.Image
import javafx.stage.Stage import javafx.stage.Stage
import org.hso.texturesyncclient.controller.SettingsController
import org.hso.texturesyncclient.view.startupView.StartupView import org.hso.texturesyncclient.view.startupView.StartupView
import org.hso.texturesyncclient.view.startupView.StartupViewController import org.hso.texturesyncclient.view.startupView.StartupViewController
import tornadofx.App import tornadofx.App
class Main: App(StartupView::class){ class Main : App(StartupView::class) {
//start first controller private val svc: StartupViewController by inject()
private val svc = StartupViewController()
override fun start(stage: Stage) { override fun start(stage: Stage) {
stage.minWidth = 1000.00 // Calling super.start early prevents a weird layouting bug
stage.minHeight = 500.00 // were the button of the window is white.
stage.isResizable = false // This could(?) be caused by stage and StartupView having
stage.icons.add(Image("icons/TextureSync_Icon_256x256.jpeg")) // a different min-size.
super.start(stage)
stage.minWidth = 1050.00
stage.minHeight = 700.00
stage.width = 1050.00
stage.height = 700.00
stage.isResizable = true
stage.icons.add(Image("icons/TextureSync_Icon_256x256.png"))
stage.setOnCloseRequest { System.exit(0) } stage.setOnCloseRequest { System.exit(0) }
super.start(stage) stage.scene.stylesheets.add("/css/Styles.css")
stage.scene.stylesheets.add("/css/Styles.css") // this call must be after the super call
SettingsController.init()
svc.initConnection()
} }
} }

View File

@ -3,6 +3,7 @@ package org.hso.texturesyncclient.controller
import javafx.application.Platform import javafx.application.Platform
import javafx.collections.ObservableList import javafx.collections.ObservableList
import javafx.event.EventHandler import javafx.event.EventHandler
import javafx.scene.image.Image
import javafx.stage.DirectoryChooser import javafx.stage.DirectoryChooser
import org.hso.texturesyncclient.alerts.JFXInfoAlert import org.hso.texturesyncclient.alerts.JFXInfoAlert
import org.hso.texturesyncclient.alerts.JFXOkayCancelAlert import org.hso.texturesyncclient.alerts.JFXOkayCancelAlert
@ -13,33 +14,29 @@ import org.hso.texturesyncclient.model.Sha256
import org.hso.texturesyncclient.model.Texture import org.hso.texturesyncclient.model.Texture
import org.hso.texturesyncclient.model.TextureFormat import org.hso.texturesyncclient.model.TextureFormat
import org.hso.texturesyncclient.view.importView.ImportView import org.hso.texturesyncclient.view.importView.ImportView
import org.hso.texturesyncclient.view.importView.ImportViewController
import org.hso.texturesyncclient.view.mainView.MainView import org.hso.texturesyncclient.view.mainView.MainView
import org.hso.texturesyncclient.view.mainView.MainViewController import org.hso.texturesyncclient.view.mainView.MainViewController
import org.hso.texturesyncclient.view.startupView.StartupView import org.hso.texturesyncclient.view.startupView.StartupView
import org.hso.texturesyncclient.view.startupView.StartupViewController import org.hso.texturesyncclient.view.startupView.StartupViewController
import tornadofx.Controller import tornadofx.Controller
import tornadofx.find
import tornadofx.observable import tornadofx.observable
import java.net.InetAddress
import java.util.Calendar
import java.io.File import java.io.File
import javax.imageio.ImageIO
import java.util.UUID
import java.nio.file.Files
import java.io.FileOutputStream import java.io.FileOutputStream
import java.io.IOException import java.io.IOException
import java.net.InetAddress
import java.nio.file.Files
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.*
import javax.imageio.ImageIO
class RootController : Controller() { class RootController : Controller() {
private val mvc: MainViewController by inject() private val mvc: MainViewController by inject()
private val svc: StartupViewController by inject() private val svc: StartupViewController by inject()
private val ivc: ImportViewController by inject()
private lateinit var con: Connection private lateinit var con: Connection
private lateinit var selectedTextureModel: GUIModel
private lateinit var selectedTexture: Texture
private var lastExportDir: String = System.getProperty("user.home") private var lastExportDir: String = System.getProperty("user.home")
/** /**
@ -49,7 +46,7 @@ class RootController : Controller() {
* @param tags all tags for the file * @param tags all tags for the file
*/ */
fun importTexture(path: String, name: String, tags: ObservableList<String>) { fun importTexture(path: String, name: String, tags: ObservableList<String>) {
var data = Files.readAllBytes(File(path).toPath()) // this is the image as byte array val data = Files.readAllBytes(File(path).toPath()) // this is the image as byte array
val uuid = UUID.randomUUID() val uuid = UUID.randomUUID()
val format = if (File(path).extension.toLowerCase() == "png") TextureFormat.PNG else TextureFormat.JPEG val format = if (File(path).extension.toLowerCase() == "png") TextureFormat.PNG else TextureFormat.JPEG
@ -73,7 +70,6 @@ class RootController : Controller() {
"-fx-button-type: RAISED; -fx-background-color: #2b7bbb; -fx-text-fill: #000000;" "-fx-button-type: RAISED; -fx-background-color: #2b7bbb; -fx-text-fill: #000000;"
) )
data = null //Free image
val newTexture = Texture(uuid, name, tags.toTypedArray(), format, resolution, cal, hash) val newTexture = Texture(uuid, name, tags.toTypedArray(), format, resolution, cal, hash)
@ -85,7 +81,9 @@ class RootController : Controller() {
alertImportHash.showAndWait() alertImportHash.showAndWait()
} catch (e: Exception) { } catch (e: Exception) {
alertImport.showAndWait() alertImport.showAndWait()
println(e)
} }
} }
/** /**
@ -102,7 +100,7 @@ class RootController : Controller() {
println("[auto] server found") println("[auto] server found")
con = foundServer con = foundServer
con.ping() con.ping()
println("auto Connection to Server successful") println("[auto] Connection to Server successful")
switchStartupToMain() switchStartupToMain()
showAll() showAll()
} else { } else {
@ -110,7 +108,7 @@ class RootController : Controller() {
} }
} catch (e: Exception) { } catch (e: Exception) {
println(e) println(e)
println("auto Connection to Server NOT successful") println("[auto] Connection to Server NOT successful")
} }
if (SettingsController.serverAddressIsSet()) { if (SettingsController.serverAddressIsSet()) {
println("[file] try connect with settings file") println("[file] try connect with settings file")
@ -142,6 +140,17 @@ class RootController : Controller() {
} catch (e: Exception) { } catch (e: Exception) {
println(e) println(e)
println("Connection to Server NOT successful") 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()
}
} }
} }
} }
@ -167,26 +176,6 @@ class RootController : Controller() {
return previewList return previewList
} }
// TODO this could be a companion object
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)
}
}
/** /**
* save the texture file to a local directory * save the texture file to a local directory
* @param data the texture as meta element * @param data the texture as meta element
@ -241,23 +230,24 @@ class RootController : Controller() {
sdf.format(data.addedOn.time) sdf.format(data.addedOn.time)
) )
mvc.setTags(data.tags.toList().observable()) mvc.setTags(data.tags.toList().observable())
selectedTexture = data
mvc.setVisibleMetaTags(true) mvc.setVisibleMetaTags(true)
} }
/** /**
* remove a texture from the FolderView and the server * remove a texture from the FolderView and the server
* @param data the texture as meta element
*/ */
fun deleteTexture(data: Texture) { fun deleteTexture() {
val dialogDelete = JFXOkayCancelAlert( val dialogDelete = JFXOkayCancelAlert(
"Löschen", "Löschen",
"Textur wirklich löschen?", "Textur ${selectedTextureModel.data.name} wirklich löschen?",
"-fx-button-type: RAISED; -fx-background-color: #2b7bbb; -fx-text-fill: #000000;" "-fx-button-type: RAISED; -fx-background-color: #2b7bbb; -fx-text-fill: #000000;"
) )
dialogDelete.okayAction = EventHandler { dialogDelete.okayAction = EventHandler {
mvc.removeTextureFromView(data) con.deleteTexture(selectedTextureModel.data)
con.deleteTexture(data) mvc.removeTextureFromView(selectedTextureModel.data)
// reset the DetailView
mvc.setVisibleMetaTags(false)
mvc.setPreview3DTexture(Image("icons/TextureSync_Icon_256x256.jpeg"))
} }
dialogDelete.cancelAction = EventHandler { dialogDelete.cancelAction = EventHandler {
// Do nothing // Do nothing
@ -265,28 +255,61 @@ class RootController : Controller() {
dialogDelete.showAndWait() dialogDelete.showAndWait()
} }
/** fun updateTexture(name: String, tags: Array<String>) {
* send a changed texture to the server val newTexture = selectedTextureModel.data.copy(
* @param chips the new tag list tags = tags,
*/ name = name
fun updateTexture(chips: ObservableList<String>) {
val uuid = UUID.randomUUID()
val newTexture = Texture(
uuid,
selectedTexture.name,
chips.toTypedArray(),
selectedTexture.format,
selectedTexture.resolution,
selectedTexture.addedOn,
selectedTexture.textureHash
) )
con.updateTexture(selectedTexture, newTexture, con.getTextureFile(selectedTexture.textureHash)) 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 * show all available textures at start
*/ */
fun showAll() { private fun showAll() {
queryElements(mvc.getTags()) 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)
}
}
}
} }

View File

@ -26,7 +26,7 @@ class SettingsController {
dirPath = if (osName.contains("Windows")) { dirPath = if (osName.contains("Windows")) {
"$userHome/Documents/TextureSync" "$userHome/Documents/TextureSync"
} else { } else {
"$userHome/.TextureSync" "$userHome/.config/TextureSync"
} }
settingsFile = File("$dirPath/config.xml") //open Settings file settingsFile = File("$dirPath/config.xml") //open Settings file

View File

@ -329,4 +329,4 @@ class Connection(val address: InetAddress, val port: Int = 10796) : Closeable {
} }
} }
} }

View File

@ -30,7 +30,7 @@ internal data class InternalTexture(
resolution = arrayOf(tex.resolution.first, tex.resolution.second), resolution = arrayOf(tex.resolution.first, tex.resolution.second),
added_on = arrayOf( added_on = arrayOf(
tex.addedOn.get(Calendar.YEAR), // tex.addedOn.get(Calendar.YEAR), //
tex.addedOn.get(Calendar.MONTH), // tex.addedOn.get(Calendar.MONTH) + 1, //
tex.addedOn.get(Calendar.DAY_OF_MONTH) tex.addedOn.get(Calendar.DAY_OF_MONTH)
), ),
texture_hash = tex.textureHash.toString() texture_hash = tex.textureHash.toString()
@ -57,4 +57,4 @@ internal data class InternalTexture(
throw ConnectionInvalidJsonException() throw ConnectionInvalidJsonException()
} }
} }
} }

View File

@ -13,7 +13,7 @@ enum class TextureFormat {
data class Texture( data class Texture(
val id : UUID, val id : UUID,
val name : String, val name : String,
val tags : Array<String>, var tags : Array<String>,
val format : TextureFormat, val format : TextureFormat,
val resolution : Pair<Int, Int>, val resolution : Pair<Int, Int>,
val addedOn : Calendar, val addedOn : Calendar,

View File

@ -12,9 +12,11 @@ import javafx.scene.layout.BackgroundFill
import javafx.scene.layout.CornerRadii import javafx.scene.layout.CornerRadii
import javafx.scene.layout.VBox import javafx.scene.layout.VBox
import javafx.scene.paint.Paint import javafx.scene.paint.Paint
import tornadofx.* import tornadofx.addClass
import tornadofx.find
import tornadofx.paddingTop
class GUIModel constructor(var data: Texture, img: Image) : VBox(){ class GUIModel constructor(var data: Texture, img: Image) : VBox() {
private var image = ImageView() private var image = ImageView()
private var label = Label() private var label = Label()
@ -22,13 +24,13 @@ class GUIModel constructor(var data: Texture, img: Image) : VBox(){
private var exportItem = MenuItem("exportiern") private var exportItem = MenuItem("exportiern")
private var deleteItem = MenuItem("löschen") private var deleteItem = MenuItem("löschen")
private val gmc = find(GUIModelController::class) private val gmc = find(GUIModelController::class)
init { init {
super.setPadding(Insets(5.0, 5.0, 5.0, 5.0)) super.setPadding(Insets(5.0, 5.0, 5.0, 5.0))
super.getChildren().addAll(image, label) super.getChildren().addAll(image, label)
super.setOnContextMenuRequested { p0 -> contextMenu.show(this@GUIModel, p0.screenX, p0.screenY) } super.setOnContextMenuRequested { p0 -> contextMenu.show(this@GUIModel, p0.screenX, p0.screenY) }
super.setOnMouseClicked{ super.setOnMouseClicked {
if (gmc.isLastSelectedInitialized()) { if (gmc.isLastSelectedInitialized()) {
gmc.lastSelected.background = Background.EMPTY gmc.lastSelected.background = Background.EMPTY
this.background = Background(BackgroundFill(Paint.valueOf("#2b7bbb"), CornerRadii.EMPTY, Insets.EMPTY)) this.background = Background(BackgroundFill(Paint.valueOf("#2b7bbb"), CornerRadii.EMPTY, Insets.EMPTY))
@ -38,13 +40,22 @@ class GUIModel constructor(var data: Texture, img: Image) : VBox(){
gmc.lastSelected = this gmc.lastSelected = this
} }
gmc.previewSelectedAction(data) gmc.previewSelectedAction(data)
gmc.setSelected(this)
} }
label.addClass("metadata")
label.paddingTop = 5.0 label.paddingTop = 5.0
label.prefWidth = 128.0 label.prefWidth = 128.0
label.alignment = Pos.CENTER label.alignment = Pos.CENTER
label.text = data.name
label.background = Background(BackgroundFill(Paint.valueOf("#FFFF2b"), CornerRadii.EMPTY, Insets.EMPTY)) label.text = if (data.name.length > 15) {
"${data.name.subSequence(0, 14)}.."
} else {
data.name
}
label.background = Background(BackgroundFill(Paint.valueOf("#3a3a3a"), CornerRadii.EMPTY, Insets.EMPTY))
image.fitHeight = 128.0 image.fitHeight = 128.0
image.fitWidth = 128.0 image.fitWidth = 128.0
@ -55,7 +66,7 @@ class GUIModel constructor(var data: Texture, img: Image) : VBox(){
} }
deleteItem.setOnAction { deleteItem.setOnAction {
gmc.delete(data) gmc.delete()
} }
contextMenu.items.add(exportItem) contextMenu.items.add(exportItem)

View File

@ -3,7 +3,7 @@ package org.hso.texturesyncclient.model
import org.hso.texturesyncclient.controller.RootController import org.hso.texturesyncclient.controller.RootController
import tornadofx.Controller import tornadofx.Controller
class GUIModelController: Controller() { class GUIModelController : Controller() {
private val rootc = find(RootController::class) private val rootc = find(RootController::class)
@ -14,11 +14,15 @@ class GUIModelController: Controller() {
rootc.exportTexture(data) rootc.exportTexture(data)
} }
fun delete(data: Texture) { fun delete() {
rootc.deleteTexture(data) rootc.deleteTexture()
} }
fun previewSelectedAction(data: Texture) { fun previewSelectedAction(data: Texture) {
rootc.showDetail(data) rootc.showDetail(data)
} }
fun setSelected(model: GUIModel) {
rootc.setSelectedTexture(model)
}
} }

View File

@ -10,6 +10,7 @@ import javafx.scene.layout.BackgroundFill
import javafx.scene.layout.CornerRadii import javafx.scene.layout.CornerRadii
import javafx.scene.paint.Paint import javafx.scene.paint.Paint
import javafx.scene.layout.Priority import javafx.scene.layout.Priority
import org.hso.texturesyncclient.view.mainView.Preview3D
import tornadofx.* import tornadofx.*
class ImportView : View("TextureSync") { class ImportView : View("TextureSync") {
@ -18,17 +19,21 @@ class ImportView : View("TextureSync") {
val tfName = JFXTextField() val tfName = JFXTextField()
val cvTags = JFXChipView<String>() val cvTags = JFXChipView<String>()
val btnImport = JFXButton("Importieren") val btnImport = JFXButton("Importieren")
val btnBack = JFXButton("Zurück")
val preview = Preview3D()
private val btnBack = JFXButton("Zurück")
private val ivc: ImportViewController by inject() private val ivc: ImportViewController by inject()
init { init {
btnImport.isVisible = false btnImport.isVisible = false
preview.root.isVisible = false
} }
override val root = borderpane { override val root = borderpane {
minWidth = 1000.0 prefWidth = FX.primaryStage.width
minHeight = 500.0 prefHeight = FX.primaryStage.height
background = Background(BackgroundFill(Paint.valueOf("#2b2b2b"), CornerRadii.EMPTY, Insets.EMPTY)) background = Background(BackgroundFill(Paint.valueOf("#2b2b2b"), CornerRadii.EMPTY, Insets.EMPTY))
center = vbox(50) { center = vbox(50) {
@ -39,6 +44,8 @@ class ImportView : View("TextureSync") {
style = "-fx-font: 20px Verdana; -fx-text-fill: #2b7bbb;" style = "-fx-font: 20px Verdana; -fx-text-fill: #2b7bbb;"
} }
add(preview)
vbox(20) { vbox(20) {
hbox(10) { hbox(10) {
add(tfFilePath) add(tfFilePath)

View File

@ -1,9 +1,11 @@
package org.hso.texturesyncclient.view.importView package org.hso.texturesyncclient.view.importView
import javafx.scene.image.Image
import javafx.stage.FileChooser
import org.hso.texturesyncclient.controller.RootController import org.hso.texturesyncclient.controller.RootController
import tornadofx.Controller import tornadofx.Controller
import javafx.stage.FileChooser
import java.io.File import java.io.File
import java.io.FileInputStream
class ImportViewController : Controller() { class ImportViewController : Controller() {
@ -29,12 +31,24 @@ class ImportViewController : Controller() {
iv.tfFilePath.text = file.absolutePath iv.tfFilePath.text = file.absolutePath
iv.tfName.text = file.nameWithoutExtension iv.tfName.text = file.nameWithoutExtension
lastImportDir = file.parent.toString() //store last user chosen dir lastImportDir = file.parent.toString() //store last user chosen dir
runAsync {
try {
val fileInput = FileInputStream(file.absolutePath)
val img = Image(fileInput)
iv.preview.setTexture(img)
iv.preview.root.isVisible = true
} catch (e: Exception) {
// Got a catch'em all
println(e.message)
}
}
} }
} }
fun btnImportAction() { fun btnImportAction() {
rootc.importTexture(iv.tfFilePath.text, iv.tfName.text, iv.cvTags.chips) rootc.importTexture(iv.tfFilePath.text, iv.tfName.text, iv.cvTags.chips)
rootc.switchImportToMain() RootController.switchImportToMain()
iv.tfFilePath.clear() iv.tfFilePath.clear()
iv.tfName.clear() iv.tfName.clear()
iv.cvTags.chips.clear() iv.cvTags.chips.clear()
@ -46,7 +60,7 @@ class ImportViewController : Controller() {
} }
fun btnBackAction() { fun btnBackAction() {
rootc.switchImportToMain() RootController.switchImportToMain()
iv.tfFilePath.clear() iv.tfFilePath.clear()
iv.tfName.clear() iv.tfName.clear()
iv.cvTags.chips.clear() iv.cvTags.chips.clear()

View File

@ -2,10 +2,9 @@ package org.hso.texturesyncclient.view.mainView
import com.jfoenix.controls.JFXButton import com.jfoenix.controls.JFXButton
import com.jfoenix.controls.JFXChipView import com.jfoenix.controls.JFXChipView
import com.jfoenix.controls.JFXTextField
import javafx.geometry.Insets import javafx.geometry.Insets
import javafx.geometry.Orientation import javafx.geometry.Orientation
import javafx.geometry.Pos
import javafx.scene.control.Label
import javafx.scene.image.Image import javafx.scene.image.Image
import javafx.scene.layout.Background import javafx.scene.layout.Background
import javafx.scene.layout.BackgroundFill import javafx.scene.layout.BackgroundFill
@ -13,16 +12,35 @@ import javafx.scene.layout.CornerRadii
import javafx.scene.paint.Paint import javafx.scene.paint.Paint
import tornadofx.* import tornadofx.*
class DetailView: View() { class DetailView : View() {
val preview = Preview3D() val preview = Preview3D()
val metaLabel = Label("Auflösung: 8MP\nName: Texture.png\nAndere: was anderes\nEinfügedatum: 31.02.2019")
val cvTags = JFXChipView<String>() val cvTags = JFXChipView<String>()
val btnImport = JFXButton("+")
init { val nameInfo = JFXTextField().addClass("metadata")
// set a default texture val resolutionInfo = label().addClass("metadata")
preview.setTexture(Image("icons/TextureSync_Icon_256x256.jpeg")) val formatInfo = label().addClass("metadata")
val dateInfo = label().addClass("metadata")
val btnSubmit = JFXButton("Ändern").addClass("btn-blue")
val metadataPanel = gridpane {
row {
label("Name ").addClass("metadata")
add(nameInfo)
}
row {
label("Auflösung ").addClass("metadata")
add(resolutionInfo)
}
row {
label("Format ").addClass("metadata")
add(formatInfo)
}
row {
label("Einfügedatum ").addClass("metadata")
add(dateInfo)
}
} }
override val root = form { override val root = form {
@ -31,42 +49,32 @@ class DetailView: View() {
fieldset(labelPosition = Orientation.VERTICAL) { fieldset(labelPosition = Orientation.VERTICAL) {
field{ field {
vbox(7) { vbox(7) {
add(preview) add(preview)
} }
} }
field { field {
paddingTop = 2 add(metadataPanel)
paddingBottom = 3
add(metaLabel)
} }
field { field {
minHeight = 155.0 minHeight = 155.0
add(cvTags) add(cvTags)
} }
field { field {
hbox(alignment = Pos.CENTER_RIGHT) { add(btnSubmit)
add(btnImport)
}
} }
} }
}
style { init {
metaLabel.style = "-fx-text-fill: #2b7bbb;" // set a default texture
preview.setTexture(Image("icons/TextureSync_Icon_256x256.jpeg"))
cvTags.minHeight = 145.0 btnSubmit.useMaxWidth = true
cvTags.paddingAll = 3.0
cvTags.style = "-fx-background-color: #53585b; -fx-text-inner-color: #b15b2e;"
btnImport.buttonType = JFXButton.ButtonType.RAISED
btnImport.styleClass.add("jfx-floating-action-button")
}
} }
} }

View File

@ -13,12 +13,7 @@ class FolderView : View("FolderView"){
hgap = 5.0 hgap = 5.0
vgap = 5.0 vgap = 5.0
paddingAll = 10.0 paddingAll = 10.0
prefWidth = 732.0
prefHeight = 401.0
background = Background(BackgroundFill(Paint.valueOf("#2b2b2b"), CornerRadii.EMPTY, Insets.EMPTY)) background = Background(BackgroundFill(Paint.valueOf("#2b2b2b"), CornerRadii.EMPTY, Insets.EMPTY))
style {
}
} }
} }

View File

@ -1,8 +1,8 @@
package org.hso.texturesyncclient.view.mainView package org.hso.texturesyncclient.view.mainView
import com.jfoenix.controls.JFXButton
import com.jfoenix.controls.JFXChipView import com.jfoenix.controls.JFXChipView
import javafx.geometry.Insets import javafx.geometry.Insets
import javafx.scene.control.ScrollPane
import javafx.scene.layout.Background import javafx.scene.layout.Background
import javafx.scene.layout.BackgroundFill import javafx.scene.layout.BackgroundFill
@ -13,51 +13,53 @@ import tornadofx.*
class MainView : View("TextureSync") { class MainView : View("TextureSync") {
val cvSearch = JFXChipView<String>() val cvSearch = JFXChipView<String>()
private val btnImport = JFXButton("+")
val folderView = find(FolderView::class) val folderView = find(FolderView::class)
val detailView = find(DetailView::class) val detailView = find(DetailView::class)
private val mvc: MainViewController by inject() private val mvc: MainViewController by inject()
override val root = borderpane { override val root = anchorpane {
background = Background(BackgroundFill(Paint.valueOf("#2b2b2b"), CornerRadii.EMPTY, Insets.EMPTY)) background = Background(BackgroundFill(Paint.valueOf("#2b2b2b"), CornerRadii.EMPTY, Insets.EMPTY))
minWidth = 1000.0 prefWidth = FX.primaryStage.width
maxWidth = 1000.0 prefHeight = FX.primaryStage.height
minHeight = 500.0
maxHeight = 500.0
left = vbox { borderpane {
//background = Background(BackgroundFill(Paint.valueOf("#2b2b2b"), CornerRadii.EMPTY, Insets.EMPTY)) right = detailView.root
anchorpane{ center = vbox {
this.fitToParentWidth()
paddingAll = 5.0
add(cvSearch) add(cvSearch)
}
anchorpane {
scrollpane { scrollpane {
this.fitToParentSize()
this.vbarPolicy = ScrollPane.ScrollBarPolicy.ALWAYS
add(folderView.root)
style = "-fx-background-color:transparent;" style = "-fx-background-color:transparent;"
isFitToWidth = true
isFitToHeight = true
add(folderView.root)
} }
} }
anchorpaneConstraints {
topAnchor = 0
bottomAnchor = 0
rightAnchor = 0
leftAnchor = 0
}
} }
right = detailView.root add(btnImport)
style { style {
cvSearch.promptText = "Suche" cvSearch.promptText = "Suche"
cvSearch.paddingAll = 5.0 cvSearch.paddingAll = 5.0
cvSearch.minHeight = 70.0 cvSearch.minHeight = 65.0
cvSearch.style = "-fx-background-color: #53585b; -fx-text-inner-color: #b15b2e;" cvSearch.style = "-fx-background-color: #53585b; -fx-text-inner-color: #b15b2e;"
cvSearch.anchorpaneConstraints {
topAnchor = 3
bottomAnchor = 3
leftAnchor = 3
rightAnchor = -5
}
btnImport.buttonType = JFXButton.ButtonType.RAISED
btnImport.styleClass.add("jfx-floating-action-button")
btnImport.anchorpaneConstraints {
bottomAnchor = 5
rightAnchor = 5
}
} }
// actions // actions
@ -65,14 +67,33 @@ class MainView : View("TextureSync") {
mvc.cvSearchAction(cvSearch.chips) mvc.cvSearchAction(cvSearch.chips)
} }
detailView.cvTags.chips.onChange { btnImport.setOnAction {
mvc.updateTags()
}
detailView.btnImport.setOnAction {
mvc.btnImportAction() mvc.btnImportAction()
} }
// TODO: on chipview update on name update
detailView.cvTags.chips.onChange {
detailView.btnSubmit.isVisible = true
}
detailView.nameInfo.textProperty().onChange {
detailView.btnSubmit.isVisible = true
}
detailView.btnSubmit.setOnAction {
mvc.updateTags()
detailView.btnSubmit.isVisible = false
}
//keyboard actions
shortcut("Ctrl+I") {
mvc.btnImportAction()
}
shortcut("Ctrl+E") {
mvc.scExport()
}
} }
} }

View File

@ -2,10 +2,10 @@ package org.hso.texturesyncclient.view.mainView
import javafx.collections.ObservableList import javafx.collections.ObservableList
import javafx.scene.image.Image import javafx.scene.image.Image
import org.hso.texturesyncclient.model.GUIModel
import tornadofx.Controller
import org.hso.texturesyncclient.controller.RootController import org.hso.texturesyncclient.controller.RootController
import org.hso.texturesyncclient.model.GUIModel
import org.hso.texturesyncclient.model.Texture import org.hso.texturesyncclient.model.Texture
import tornadofx.Controller
class MainViewController : Controller() { class MainViewController : Controller() {
@ -17,7 +17,6 @@ class MainViewController : Controller() {
// DetailView elements // DetailView elements
private val preview = mv.detailView.preview private val preview = mv.detailView.preview
private val metaLabel = mv.detailView.metaLabel
private val cvTags = mv.detailView.cvTags private val cvTags = mv.detailView.cvTags
private var lockUpdate: Boolean = false //lock update func when the system changes the detailview chipview private var lockUpdate: Boolean = false //lock update func when the system changes the detailview chipview
@ -32,7 +31,12 @@ class MainViewController : Controller() {
} }
fun setMeta(name: String, res: String, format: String, date: String) { fun setMeta(name: String, res: String, format: String, date: String) {
metaLabel.text = "Name: $name\nAuflösung: $res\nFormat: $format\nEinfügedatum: $date" with(mv.detailView) {
nameInfo.text = name
formatInfo.text = format
resolutionInfo.text = res
dateInfo.text = date
}
} }
fun setTags(chips: ObservableList<String>) { fun setTags(chips: ObservableList<String>) {
@ -42,14 +46,17 @@ class MainViewController : Controller() {
lockUpdate = true //allow update with onChange lockUpdate = true //allow update with onChange
} }
fun getTags(): ObservableList<String>{ fun getTags(): ObservableList<String> {
return cvTags.chips return cvTags.chips
} }
fun updateTags() { fun updateTags() {
if (lockUpdate) { //the chipView was changed by the user if (lockUpdate) { //the chipView was changed by the user
println("Tags changed") println("Tags changed")
rootc.updateTexture(cvTags.chips) rootc.updateTexture(
tags = cvTags.chips.toTypedArray(),
name = mv.detailView.nameInfo.text
)
} }
} }
@ -60,6 +67,7 @@ class MainViewController : Controller() {
folderView.children.clear() folderView.children.clear()
mv.cvSearch.isDisable = true mv.cvSearch.isDisable = true
setPreview3DTexture(Image("icons/TextureSync_Icon_256x256.jpeg")) // reset the 3DPreview to the logo setPreview3DTexture(Image("icons/TextureSync_Icon_256x256.jpeg")) // reset the 3DPreview to the logo
RootController.selectedTexture = null
runAsync { runAsync {
rootc.queryElements(tags) rootc.queryElements(tags)
@ -70,7 +78,7 @@ class MainViewController : Controller() {
} }
fun btnImportAction() { fun btnImportAction() {
rootc.switchMainToImport() RootController.switchMainToImport()
} }
fun removeTextureFromView(data: Texture) { fun removeTextureFromView(data: Texture) {
@ -79,14 +87,20 @@ class MainViewController : Controller() {
.ifPresent { x -> folderView.children.remove(x) } .ifPresent { x -> folderView.children.remove(x) }
} }
fun setVisibleMetaTags(bool: Boolean){ fun setVisibleMetaTags(bool: Boolean) {
if(bool){ if (bool) {
metaLabel.isVisible = true mv.detailView.metadataPanel.isVisible = true
mv.detailView.btnSubmit.isVisible = false
cvTags.isVisible = true cvTags.isVisible = true
}else{ } else {
metaLabel.isVisible = false mv.detailView.metadataPanel.isVisible = false
mv.detailView.btnSubmit.isVisible = false
cvTags.isVisible = false cvTags.isVisible = false
} }
} }
fun scExport() {
RootController.selectedTexture?.let { rootc.exportTexture(RootController.selectedTexture!!) }
}
} }

View File

@ -36,7 +36,6 @@ class Preview3D : View("Preview3D") {
pointLightFront.rotate = 90.0 pointLightFront.rotate = 90.0
} }
override val root = stackpane { override val root = stackpane {
add(dBox).apply { add(dBox).apply {

View File

@ -22,6 +22,7 @@ class StartupView : View("TextureSync") {
private val svc: StartupViewController by inject() private val svc: StartupViewController by inject()
override val root = borderpane { override val root = borderpane {
minWidth = 1000.0 minWidth = 1000.0
minHeight = 500.0 minHeight = 500.0

View File

@ -1,7 +1,6 @@
package org.hso.texturesyncclient.view.startupView package org.hso.texturesyncclient.view.startupView
import org.hso.texturesyncclient.controller.RootController import org.hso.texturesyncclient.controller.RootController
import org.hso.texturesyncclient.controller.SettingsController
import tornadofx.Controller import tornadofx.Controller
@ -10,9 +9,8 @@ class StartupViewController : Controller() {
private val sv = find(StartupView::class) private val sv = find(StartupView::class)
private val rootc = find(RootController::class) private val rootc = find(RootController::class)
init { fun initConnection() {
println("init StartupViewController") println("init StartupViewController")
SettingsController.init()
startConnectionUI() startConnectionUI()
runAsync { runAsync {
rootc.initConnection(" ") rootc.initConnection(" ")

View File

@ -88,7 +88,9 @@
-fx-min-height: -fx-pref-height; -fx-min-height: -fx-pref-height;
-fx-max-height: -fx-pref-height; -fx-max-height: -fx-pref-height;
-jfx-button-type: RAISED; -jfx-button-type: RAISED;
-fx-font-size: 25px
-fx-text-inner-color: #2b2b2b;
-fx-font-size: 20px;
} }
/******************************************************************************* /*******************************************************************************
@ -107,3 +109,37 @@
-fx-alignment: center-left; -fx-alignment: center-left;
-fx-spacing: 8; -fx-spacing: 8;
} }
.jfx-chip-view {
-fx-text-inner-color: #E0E0E0;
}
/*******************************************************************************
* *
* Buttons *
* *
******************************************************************************/
.btn-blue {
-fx-button-type: RAISED;
-fx-background-color: #3c3f41;
-fx-text-fill: #2b7bbb;
-fx-padding: 10;
}
.btn-orange {
-fx-button-type: RAISED;
-fx-background-color: #b15b2e;
-fx-text-fill: #3c3f41;
}
/*******************************************************************************
* *
* DetailView *
* *
******************************************************************************/
.metadata {
-fx-font: 14px Verdana;
-fx-text-fill: #E0E0E0;
}

View File

@ -0,0 +1 @@
<svg width="640" height="640" xmlns="http://www.w3.org/2000/svg"><defs><radialGradient id="a" cx="0.2" cy="-0.5" r="1.7"><stop offset="40%" stop-color="#8c8c8c"/><stop offset="100%" stop-color="#4c4c4c"/></radialGradient><radialGradient id="b" cx="0.2" cy="0.2" fx="0.34" fy="0.32" r="0.9"><stop offset="0%" stop-color="#fbf6f0"/><stop offset="50%" stop-color="#eadec4"/><stop offset="100%" stop-color="#aba390"/></radialGradient><radialGradient id="c" cx="0.2" cy="0.2" fx="0.34" fy="0.32" r="0.9"><stop offset="5%" stop-color="#fbf1cd"/><stop offset="50%" stop-color="#ffba00"/><stop offset="100%" stop-color="#bc8602"/></radialGradient></defs><path d="M158.58 102.89C144.48 110.79 143.14 130.93 155.49 141.35C169.62 153.27 184.17 164.75 199.13 175.69C138.27 240.95 105.0 337.14 105.0 426.0C105.0 525.49 179.5 590.92 278.99 591.0C342.5 591.05 406.69 553.62 449.59 506.78C501.0 450.65 531.88 370.14 532.0 294.02C532.06 254.61 524.06 213.61 505.46 178.86C487.92 146.11 450.51 118.09 413.38 117.01C388.12 116.27 362.24 125.41 340.98 139.06C331.11 145.4 321.78 152.65 313.04 160.6C313.88 131.47 312.82 102.25 309.97 73.31C308.35 56.96 293.5 46.31 277.86 51.34C236.62 64.58 196.37 81.72 158.58 102.89Z" fill="#000"/><path d="M165.42 115.11C158.26 119.12 158.24 125.36 164.51 130.65C201.33 161.71 241.11 189.73 283.36 212.86C290.09 216.54 295.26 213.92 296.04 206.29C300.48 162.65 300.34 118.34 296.03 74.69C295.17 65.95 290.5 61.98 282.14 64.66C241.79 77.63 202.4 94.39 165.42 115.11Z" fill="url(#a)"/><path d="M220.6 190.82C238.75 203.14 257.44 214.63 276.64 225.14C282.11 228.13 288.25 228.46 293.76 226.78L496.27 366.27C484.19 411.93 461.33 455.47 430.41 489.22C397.54 525.11 350.51 555.58 301.99 563.18L136.05 367.03C147.1 301.77 176.06 237.27 220.6 190.82Z" fill="url(#b)"/><path d="M293.76 226.78C302.1 224.23 309.01 217.1 309.96 207.71C310.21 205.29 310.44 202.86 310.66 200.43C323.57 185.24 338.43 171.6 355.02 160.94C371.91 150.09 392.56 142.41 412.62 142.99C440.73 143.82 469.27 166.35 482.54 191.14C499.13 222.12 506.06 258.84 506.0 293.98C505.96 317.93 502.59 342.39 496.27 366.27L330.0 369.0L301.99 563.18C294.35 564.38 286.68 565.01 279.01 565.0C192.51 564.93 131.0 512.5 131.0 426.0C131.0 406.59 132.7 386.78 136.05 367.03L290.0 332.0L293.76 226.78Z" fill="url(#c)"/></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,15 @@
- herunterladen (Release Gitea)
- installiern (Java VM)
- starten
- connecten
- neue textur einfügen
- query mit Tags
- query mit Name
- query mit Auflösung
- query mit Datum
- query mit Kombination
- exportieren
- ändern
- löschen
- settings file löschen

View File

@ -0,0 +1,7 @@
- herunterladen (Release Gitea)
- installiern (service daemon)
- starten
- loggen
- stoppen
- backups machen
- backups wieder einspielen

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,4 @@
- kleine Präsentation über Projekt
- Idee (Problem der Verwaltung vieler Texturen)
- Ziele (einfach, lokale Daten, gemeinschafftlicher Zugriff)
- Gelerntes (gute Planung, Tests, Versionsverwaltung, Issue-Tracker)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,9 @@
<phases/> <phases/>
<calendars> <calendars>
<day-types> <day-types>
<day-type id="0" name="Working" description="A default working day"/> <day-type id="0" name="Arbeiten" description="Ein Vorgabe-Arbeitstag"/>
<day-type id="1" name="Nonworking" description="A default non working day"/> <day-type id="1" name="Nicht Arbeiten" description="Ein Vorgabetag, an dem nicht gearbeitet wird"/>
<day-type id="2" name="Use base" description="Use day from base calendar"/> <day-type id="2" name="Basis verwenden" description="Tag vom Basiskalender verwenden"/>
</day-types> </day-types>
<calendar id="1" name="Vorgabe"> <calendar id="1" name="Vorgabe">
<default-week mon="1" tue="0" wed="0" thu="1" fri="1" sat="0" sun="1"/> <default-week mon="1" tue="0" wed="0" thu="1" fri="1" sat="0" sun="1"/>
@ -16,7 +16,9 @@
<interval start="1300" end="1700"/> <interval start="1300" end="1700"/>
</overridden-day-type> </overridden-day-type>
</overridden-day-types> </overridden-day-types>
<days/> <days>
<day date="20190613" type="day-type" id="0"/>
</days>
</calendar> </calendar>
</calendars> </calendars>
<tasks> <tasks>
@ -92,88 +94,82 @@
<predecessor id="1" predecessor-id="10" type="FS"/> <predecessor id="1" predecessor-id="10" type="FS"/>
</predecessors> </predecessors>
</task> </task>
<task id="19" name="Realisation" note="" work="1065600" start="20190423T000000Z" end="20190511T170000Z" work-start="20190423T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"> <task id="19" name="Realisation" note="" work="1641600" start="20190416T133640Z" end="20190612T170000Z" work-start="20190416T133640Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
<predecessors> <predecessors>
<predecessor id="1" predecessor-id="18" type="FS"/> <predecessor id="1" predecessor-id="18" type="FS"/>
</predecessors> </predecessors>
<task id="20" name="Einrichtung von Tests" note="" work="28800" start="20190423T000000Z" end="20190423T170000Z" work-start="20190423T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"> <task id="20" name="Einrichtung von Tests" note="" work="28800" start="20190416T133640Z" end="20190417T133640Z" work-start="20190416T133640Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
<predecessors> <predecessors>
<predecessor id="1" predecessor-id="11" type="FS"/> <predecessor id="1" predecessor-id="11" type="FS"/>
</predecessors> </predecessors>
<task id="21" name="Client Tests" note="" work="28800" start="20190423T000000Z" end="20190423T170000Z" work-start="20190423T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"> </task>
<task id="21" name="Client" note="" work="1123200" start="20190416T133640Z" end="20190612T170000Z" work-start="20190416T133640Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
<predecessors>
<predecessor id="1" predecessor-id="11" type="FS"/>
</predecessors>
<task id="22" name="UI" note="" work="288000" start="20190416T133640Z" end="20190423T133640Z" work-start="20190416T133640Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
<task id="23" name="Previews" note="" work="86400" start="20190416T133640Z" end="20190423T133640Z" work-start="20190416T133640Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work"/>
<task id="24" name="Filter UI" note="" work="86400" start="20190416T133640Z" end="20190423T133640Z" work-start="20190416T133640Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work"/>
<task id="25" name="3D Visualisierung" note="" work="57600" start="20190416T133640Z" end="20190420T133640Z" work-start="20190416T133640Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work"/>
<task id="26" name="Dateien hinzuf&#xFC;gen" note="" work="28800" start="20190416T133640Z" end="20190417T133640Z" work-start="20190416T133640Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work"/>
<task id="27" name="Dateien lokal abspeichern" note="" work="28800" start="20190416T133640Z" end="20190417T133640Z" work-start="20190416T133640Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work"/>
</task>
<task id="28" name="Grund Architektur" note="" work="662400" start="20190423T000000Z" end="20190612T170000Z" work-start="20190423T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
<constraint type="start-no-earlier-than" time="20190423T000000Z"/>
</task>
<task id="29" name="Protokoll implementieren" note="" work="172800" start="20190423T000000Z" end="20190504T170000Z" work-start="20190423T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
<constraint type="start-no-earlier-than" time="20190423T000000Z"/> <constraint type="start-no-earlier-than" time="20190423T000000Z"/>
</task> </task>
</task> </task>
<task id="22" name="Client" note="" work="547200" start="20190423T000000Z" end="20190504T170000Z" work-start="20190423T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"> <task id="30" name="Server" note="" work="489600" start="20190423T000000Z" end="20190511T170000Z" work-start="20190423T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
<predecessors> <predecessors>
<predecessor id="1" predecessor-id="11" type="FS"/> <predecessor id="1" predecessor-id="11" type="FS"/>
</predecessors> </predecessors>
<task id="23" name="UI" note="" work="288000" start="20190423T170000Z" end="20190430T170000Z" work-start="20190424T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"> <task id="31" name="Dateien speichern/verwalten" note="" work="172800" start="20190423T000000Z" end="20190504T170000Z" work-start="20190423T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
<predecessors>
<predecessor id="1" predecessor-id="21" type="FS"/>
</predecessors>
<task id="24" name="Previews" note="" work="86400" start="20190423T170000Z" end="20190430T170000Z" work-start="20190424T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"/>
<task id="25" name="Filter UI" note="" work="86400" start="20190423T170000Z" end="20190430T170000Z" work-start="20190424T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"/>
<task id="26" name="3D Visualisierung" note="" work="57600" start="20190423T170000Z" end="20190427T170000Z" work-start="20190424T080000Z" percent-complete="50" priority="0" type="normal" scheduling="fixed-work"/>
<task id="27" name="Dateien hinzuf&#xFC;gen" note="" work="28800" start="20190423T170000Z" end="20190424T170000Z" work-start="20190424T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"/>
<task id="28" name="Dateien lokal abspeichern" note="" work="28800" start="20190423T170000Z" end="20190424T170000Z" work-start="20190424T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"/>
</task>
<task id="29" name="Grund Architektur" note="" work="86400" start="20190423T000000Z" end="20190427T170000Z" work-start="20190423T080000Z" percent-complete="70" priority="0" type="normal" scheduling="fixed-work">
<constraint type="start-no-earlier-than" time="20190423T000000Z"/>
</task>
<task id="30" name="Protokoll implementieren" note="" work="172800" start="20190423T000000Z" end="20190504T170000Z" work-start="20190423T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
<constraint type="start-no-earlier-than" time="20190423T000000Z"/>
</task>
</task>
<task id="31" name="Server" note="" work="489600" start="20190423T000000Z" end="20190511T170000Z" work-start="20190423T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
<predecessors>
<predecessor id="1" predecessor-id="11" type="FS"/>
</predecessors>
<task id="32" name="Dateien speichern/verwalten" note="" work="172800" start="20190423T000000Z" end="20190504T170000Z" work-start="20190423T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
<constraint type="must-start-on" time="20190423T000000Z"/> <constraint type="must-start-on" time="20190423T000000Z"/>
</task> </task>
<task id="33" name="Protokoll implementieren" note="" work="172800" start="20190423T000000Z" end="20190504T170000Z" work-start="20190423T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work"> <task id="32" name="Protokoll implementieren" note="" work="172800" start="20190423T000000Z" end="20190504T170000Z" work-start="20190423T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
<constraint type="must-start-on" time="20190423T000000Z"/> <constraint type="must-start-on" time="20190423T000000Z"/>
</task> </task>
<task id="34" name="Suche implementieren" note="" work="86400" start="20190504T170000Z" end="20190511T170000Z" work-start="20190507T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work"> <task id="33" name="Suche implementieren" note="" work="86400" start="20190504T170000Z" end="20190511T170000Z" work-start="20190507T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
<predecessors> <predecessors>
<predecessor id="1" predecessor-id="32" type="FS"/> <predecessor id="1" predecessor-id="31" type="FS"/>
</predecessors> </predecessors>
</task> </task>
<task id="35" name="Hauptlogik implementieren" note="Haupts&#xE4;chlich Glue-Code&#10;&#10;" work="57600" start="20190504T170000Z" end="20190508T170000Z" work-start="20190507T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work"> <task id="34" name="Hauptlogik implementieren" note="Haupts&#xE4;chlich Glue-Code&#10;&#10;" work="57600" start="20190504T170000Z" end="20190508T170000Z" work-start="20190507T080000Z" percent-complete="100" priority="0" type="normal" scheduling="fixed-work">
<predecessors> <predecessors>
<predecessor id="1" predecessor-id="33" type="FS"/>
<predecessor id="1" predecessor-id="32" type="FS"/> <predecessor id="1" predecessor-id="32" type="FS"/>
<predecessor id="1" predecessor-id="31" type="FS"/>
</predecessors> </predecessors>
</task> </task>
</task> </task>
</task> </task>
<task id="36" name="End of Implementation" note="" work="0" start="20190511T170000Z" end="20190511T170000Z" work-start="20190511T170000Z" percent-complete="0" priority="0" type="milestone" scheduling="fixed-work"> <task id="35" name="End of Implementation" note="" work="0" start="20190612T170000Z" end="20190612T170000Z" work-start="20190612T170000Z" percent-complete="0" priority="0" type="milestone" scheduling="fixed-work">
<predecessors> <predecessors>
<predecessor id="1" predecessor-id="31" type="FS"/> <predecessor id="1" predecessor-id="30" type="FS"/>
<predecessor id="1" predecessor-id="22" type="FS"/> <predecessor id="1" predecessor-id="21" type="FS"/>
<predecessor id="1" predecessor-id="20" type="FS"/> <predecessor id="1" predecessor-id="20" type="FS"/>
</predecessors> </predecessors>
</task> </task>
<task id="37" name="Abnahme" note="" work="374400" start="20190511T170000Z" end="20190611T170000Z" work-start="20190514T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"> <task id="36" name="Abnahme" note="" work="115200" start="20190612T170000Z" end="20190613T170000Z" work-start="20190613T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
<task id="38" name="Modultests [M]" note="" work="115200" start="20190511T170000Z" end="20190521T170000Z" work-start="20190514T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"> <task id="37" name="Modultests [M]" note="" work="28800" start="20190612T170000Z" end="20190613T170000Z" work-start="20190613T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
<predecessors> <predecessors>
<predecessor id="1" predecessor-id="36" type="FS"/> <predecessor id="1" predecessor-id="35" type="FS"/>
</predecessors> </predecessors>
</task> </task>
<task id="39" name="Integrationstests [M]" note="" work="115200" start="20190521T170000Z" end="20190529T170000Z" work-start="20190522T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"> <task id="38" name="Integrationstests [M]" note="" work="28800" start="20190612T170000Z" end="20190613T170000Z" work-start="20190613T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
<predecessors> <predecessors>
<predecessor id="1" predecessor-id="38" type="FS"/> <predecessor id="1" predecessor-id="35" type="FS"/>
</predecessors> </predecessors>
</task> </task>
<task id="40" name="Systemtests [M]" note="" work="115200" start="20190529T170000Z" end="20190608T170000Z" work-start="20190601T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"> <task id="39" name="Systemtests [M]" note="" work="28800" start="20190612T170000Z" end="20190613T170000Z" work-start="20190613T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
<predecessors> <predecessors>
<predecessor id="1" predecessor-id="39" type="FS"/> <predecessor id="1" predecessor-id="35" type="FS"/>
</predecessors> </predecessors>
</task> </task>
<task id="41" name="Akzeptanztest [M]" note="" work="28800" start="20190608T170000Z" end="20190611T170000Z" work-start="20190611T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work"> <task id="40" name="Akzeptanztest [M]" note="" work="28800" start="20190612T170000Z" end="20190613T170000Z" work-start="20190613T080000Z" percent-complete="0" priority="0" type="normal" scheduling="fixed-work">
<predecessors> <predecessors>
<predecessor id="1" predecessor-id="40" type="FS"/> <predecessor id="1" predecessor-id="35" type="FS"/>
</predecessors> </predecessors>
</task> </task>
</task> </task>
@ -186,16 +182,17 @@
<resource id="4" name="Lukas" short-name="L" type="1" units="0" email="" note="" std-rate="0"/> <resource id="4" name="Lukas" short-name="L" type="1" units="0" email="" note="" std-rate="0"/>
</resources> </resources>
<allocations> <allocations>
<allocation task-id="33" resource-id="1" units="100"/> <allocation task-id="29" resource-id="1" units="100"/>
<allocation task-id="32" resource-id="1" units="100"/>
<allocation task-id="8" resource-id="1" units="100"/> <allocation task-id="8" resource-id="1" units="100"/>
<allocation task-id="13" resource-id="1" units="100"/> <allocation task-id="13" resource-id="1" units="100"/>
<allocation task-id="11" resource-id="1" units="100"/> <allocation task-id="11" resource-id="1" units="100"/>
<allocation task-id="5" resource-id="1" units="50"/> <allocation task-id="5" resource-id="1" units="50"/>
<allocation task-id="29" resource-id="2" units="50"/> <allocation task-id="28" resource-id="2" units="50"/>
<allocation task-id="8" resource-id="2" units="10"/> <allocation task-id="8" resource-id="2" units="10"/>
<allocation task-id="17" resource-id="2" units="100"/> <allocation task-id="17" resource-id="2" units="100"/>
<allocation task-id="5" resource-id="2" units="50"/> <allocation task-id="5" resource-id="2" units="50"/>
<allocation task-id="29" resource-id="3" units="50"/> <allocation task-id="28" resource-id="3" units="50"/>
<allocation task-id="15" resource-id="3" units="100"/> <allocation task-id="15" resource-id="3" units="100"/>
<allocation task-id="12" resource-id="3" units="100"/> <allocation task-id="12" resource-id="3" units="100"/>
<allocation task-id="10" resource-id="3" units="100"/> <allocation task-id="10" resource-id="3" units="100"/>

View File

@ -1,6 +1,6 @@
[package] [package]
name = "texture-sync-server" name = "texture-sync-server"
version = "0.1.0" version = "1.0.0"
authors = ["CodeSteak <codesteak@shellf.art>"] authors = ["CodeSteak <codesteak@shellf.art>"]
edition = "2018" edition = "2018"

View File

@ -24,6 +24,8 @@ use std::path::*;
fn main() -> std::io::Result<()> { fn main() -> std::io::Result<()> {
lovecraft::invoke(); lovecraft::invoke();
println!("\n\n\t=== TextureSync Server {} ===\t\n\n\n", env!("CARGO_PKG_VERSION"));
let data_path = Path::new("./data"); let data_path = Path::new("./data");
println!("loading files from {:?}", data_path); println!("loading files from {:?}", data_path);
let server_state = ServerState::new(data_path)?; let server_state = ServerState::new(data_path)?;