diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.kt b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.kt index 5be1da9ec..bc8d5015f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.kt +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.kt @@ -34,12 +34,14 @@ object Controllers { lateinit var versionController: VersionController val versionPane: Pane = loadPane("version") + lateinit var decorator: Decorator + fun initialize(stage: Stage) { this.stage = stage val decorator = Decorator(stage, mainPane, max = false) // Let root pane fix window size. - (mainPane.parent as StackPane).run { + with(mainPane.parent as StackPane) { mainPane.prefWidthProperty().bind(widthProperty()) mainPane.prefHeightProperty().bind(heightProperty()) } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.kt b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.kt index 0412adb06..2a3979f33 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.kt +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Decorator.kt @@ -18,6 +18,7 @@ package org.jackhuang.hmcl.ui import com.jfoenix.controls.JFXButton +import com.jfoenix.effects.JFXDepthManager import com.jfoenix.svg.SVGGlyph import javafx.animation.* import javafx.application.Platform @@ -31,6 +32,7 @@ import javafx.geometry.Bounds import javafx.geometry.Insets import javafx.scene.Cursor import javafx.scene.Node +import javafx.scene.control.Label import javafx.scene.control.Tooltip import javafx.scene.input.MouseEvent import javafx.scene.layout.* @@ -39,8 +41,11 @@ import javafx.scene.shape.Rectangle import javafx.stage.Screen import javafx.stage.Stage import javafx.stage.StageStyle +import javafx.scene.layout.BorderStrokeStyle +import javafx.scene.layout.BorderStroke +import org.jackhuang.hmcl.util.* -class Decorator @JvmOverloads constructor(private val primaryStage: Stage, node: Node, private val max: Boolean = true, min: Boolean = true) : VBox() { +class Decorator @JvmOverloads constructor(private val primaryStage: Stage, node: Node, private val max: Boolean = true, min: Boolean = true) : GridPane() { private var xOffset: Double = 0.0 private var yOffset: Double = 0.0 private var newX: Double = 0.0 @@ -53,66 +58,62 @@ class Decorator @JvmOverloads constructor(private val primaryStage: Stage, node: @FXML lateinit var contentPlaceHolder: StackPane @FXML lateinit var titleContainer: BorderPane @FXML lateinit var buttonsContainer: HBox - private val onCloseButtonAction: ObjectProperty - private val customMaximize: BooleanProperty + @FXML lateinit var backNavButton: JFXButton + @FXML lateinit var refreshNavButton: JFXButton + @FXML lateinit var closeNavButton: JFXButton + @FXML lateinit var refreshMenuButton: JFXButton + @FXML lateinit var addMenuButton: JFXButton + @FXML lateinit var titleLabel: Label + @FXML lateinit var leftPane: VBox + + private val onCloseButtonActionProperty: ObjectProperty = SimpleObjectProperty(Runnable { this.primaryStage.close() }) + @JvmName("onCloseButtonActionProperty") get + var onCloseButtonAction: Runnable by onCloseButtonActionProperty + + val customMaximizeProperty: BooleanProperty = SimpleBooleanProperty(false) + @JvmName("customMaximizeProperty") get + var isCustomMaximize: Boolean by customMaximizeProperty + private var maximized: Boolean = false private var originalBox: BoundingBox? = null private var maximizedBox: BoundingBox? = null @FXML lateinit var btnMin: JFXButton @FXML lateinit var btnMax: JFXButton @FXML lateinit var btnClose: JFXButton - private val minus: SVGGlyph - private val resizeMax: SVGGlyph - private val resizeMin: SVGGlyph - private val close: SVGGlyph + private val minus = SVGGlyph(0, "MINUS", "M804.571 420.571v109.714q0 22.857-16 38.857t-38.857 16h-694.857q-22.857 0-38.857-16t-16-38.857v-109.714q0-22.857 16-38.857t38.857-16h694.857q22.857 0 38.857 16t16 38.857z", Color.WHITE) + .apply { setSize(12.0, 2.0); translateY = 4.0 } + private val resizeMax = SVGGlyph(0, "RESIZE_MAX", "M726 810v-596h-428v596h428zM726 44q34 0 59 25t25 59v768q0 34-25 60t-59 26h-428q-34 0-59-26t-25-60v-768q0-34 25-60t59-26z", Color.WHITE) + .apply { setPrefSize(12.0, 12.0); setSize(12.0, 12.0) } + private val resizeMin = SVGGlyph(0, "RESIZE_MIN", "M80.842 943.158v-377.264h565.894v377.264h-565.894zM0 404.21v619.79h727.578v-619.79h-727.578zM377.264 161.684h565.894v377.264h-134.736v80.842h215.578v-619.79h-727.578v323.37h80.842v-161.686z", Color.WHITE) + .apply { setPrefSize(12.0, 12.0); setSize(12.0, 12.0) } + private val close = SVGGlyph(0, "CLOSE", "M810 274l-238 238 238 238-60 60-238-238-238 238-60-60 238-238-238-238 60-60 238 238 238-238z", Color.WHITE) + .apply { setPrefSize(12.0, 12.0); setSize(12.0, 12.0) } init { loadFXML("/assets/fxml/decorator.fxml") - this.xOffset = 0.0 - this.yOffset = 0.0 - this.allowMove = false - this.isDragging = false - this.onCloseButtonAction = SimpleObjectProperty(Runnable { this.primaryStage.close() }) - this.customMaximize = SimpleBooleanProperty(false) - this.maximized = false this.primaryStage.initStyle(StageStyle.UNDECORATED) - minus = SVGGlyph(0, "MINUS", "M804.571 420.571v109.714q0 22.857-16 38.857t-38.857 16h-694.857q-22.857 0-38.857-16t-16-38.857v-109.714q0-22.857 16-38.857t38.857-16h694.857q22.857 0 38.857 16t16 38.857z", Color.WHITE) - minus.setSize(12.0, 2.0) - minus.translateY = 4.0 - resizeMax = SVGGlyph(0, "RESIZE_MAX", "M726 810v-596h-428v596h428zM726 44q34 0 59 25t25 59v768q0 34-25 60t-59 26h-428q-34 0-59-26t-25-60v-768q0-34 25-60t59-26z", Color.WHITE) - resizeMax.setSize(12.0, 12.0) - resizeMin = SVGGlyph(0, "RESIZE_MIN", "M80.842 943.158v-377.264h565.894v377.264h-565.894zM0 404.21v619.79h727.578v-619.79h-727.578zM377.264 161.684h565.894v377.264h-134.736v80.842h215.578v-619.79h-727.578v323.37h80.842v-161.686z", Color.WHITE) - resizeMin.setSize(12.0, 12.0) - close = SVGGlyph(0, "CLOSE", "M810 274l-238 238 238 238-60 60-238-238-238 238-60-60 238-238-238-238 60-60 238 238 238-238z", Color.WHITE) - close.setSize(12.0, 12.0) btnClose.graphic = close btnMin.graphic = minus - this.btnMax.graphic = resizeMax + btnMax.graphic = resizeMax buttonsContainer.background = Background(*arrayOf(BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY))) titleContainer.addEventHandler(MouseEvent.MOUSE_CLICKED) { mouseEvent -> if (mouseEvent.clickCount == 2) { - this.btnMax.fire() + btnMax.fire() } - } if (!min) buttonsContainer.children.remove(btnMin) - if (!max) buttonsContainer.children.remove(btnMax) - titleContainer.addEventHandler(MouseEvent.MOUSE_ENTERED) { enter -> this.allowMove = true } - titleContainer.addEventHandler(MouseEvent.MOUSE_EXITED) { enter -> - if (!this.isDragging) { - this.allowMove = false - } - - } + JFXDepthManager.setDepth(titleContainer, 1) + titleContainer.addEventHandler(MouseEvent.MOUSE_ENTERED) { this.allowMove = true } + titleContainer.addEventHandler(MouseEvent.MOUSE_EXITED) { if (!this.isDragging) this.allowMove = false } this.contentPlaceHolder.children.add(node) (node as Region).setMinSize(0.0, 0.0) - this.contentPlaceHolder.border = Border(BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths(0.0, 4.0, 4.0, 4.0))) + this.border = Border(BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths(0.0, 4.0, 4.0, 4.0))) val clip = Rectangle() clip.widthProperty().bind(node.widthProperty()) clip.heightProperty().bind(node.heightProperty()) @@ -127,7 +128,7 @@ class Decorator @JvmOverloads constructor(private val primaryStage: Stage, node: val x = mouseEvent.x val y = mouseEvent.y val boundsInParent = this.boundsInParent - if (this.contentPlaceHolder.border != null && this.contentPlaceHolder.border.strokes.size > 0) { + if (this.border != null && this.border.strokes.size > 0) { val borderWidth = this.contentPlaceHolder.snappedLeftInset() if (this.isRightEdge(x, y, boundsInParent)) { if (y < borderWidth) { @@ -274,7 +275,7 @@ class Decorator @JvmOverloads constructor(private val primaryStage: Stage, node: } fun onClose() { - (this.onCloseButtonAction.get() as Runnable).run() + this.onCloseButtonAction.run() } private fun updateInitMouseValues(mouseEvent: MouseEvent) { @@ -328,18 +329,6 @@ class Decorator @JvmOverloads constructor(private val primaryStage: Stage, node: } } - fun setOnCloseButtonAction(onCloseButtonAction: Runnable) { - this.onCloseButtonAction.set(onCloseButtonAction) - } - - fun customMaximizeProperty(): BooleanProperty { - return this.customMaximize - } - - var isCustomMaximize: Boolean - get() = this.customMaximizeProperty().get() - set(customMaximize) = this.customMaximizeProperty().set(customMaximize) - fun setMaximized(maximized: Boolean) { if (this.maximized != maximized) { Platform.runLater { this.btnMax.fire() } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.kt b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.kt index 5c434ebe9..7c0259d4c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.kt +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/FXUtils.kt @@ -106,6 +106,8 @@ fun setOverflowHidden(node: Pane) { node.clip = rectangle } -val stylesheets = arrayOf(Controllers::class.java.getResource("/css/jfoenix-design.css").toExternalForm(), +val stylesheets = arrayOf( + Controllers::class.java.getResource("/css/jfoenix-fonts.css").toExternalForm(), +Controllers::class.java.getResource("/css/jfoenix-design.css").toExternalForm(), Controllers::class.java.getResource("/assets/css/jfoenix-components.css").toExternalForm(), -Controllers::class.java.getResource("/assets/css/jfoenix-main-demo.css").toExternalForm()) \ No newline at end of file + Controllers::class.java.getResource("/assets/css/jfoenix-main-demo.css").toExternalForm()) \ No newline at end of file diff --git a/HMCL/src/main/resources/assets/css/jfoenix-components.css b/HMCL/src/main/resources/assets/css/jfoenix-components.css index 14789c4ec..0f6d78e29 100644 --- a/HMCL/src/main/resources/assets/css/jfoenix-components.css +++ b/HMCL/src/main/resources/assets/css/jfoenix-components.css @@ -212,7 +212,7 @@ .jfx-tool-bar HBox { -fx-alignment: center; - -fx-spacing: 25; +/* -fx-spacing: 25;*/ -fx-padding: 0 10; } diff --git a/HMCL/src/main/resources/assets/css/jfoenix-main-demo.css b/HMCL/src/main/resources/assets/css/jfoenix-main-demo.css index 6c5c8d875..5f6cf082e 100644 --- a/HMCL/src/main/resources/assets/css/jfoenix-main-demo.css +++ b/HMCL/src/main/resources/assets/css/jfoenix-main-demo.css @@ -199,8 +199,12 @@ .jfx-tool-bar HBox { -fx-alignment: center; - -fx-spacing: 25.0; - -fx-padding: 0.0 10.0; +/* -fx-spacing: 25.0;*/ + -fx-padding: 0.0 5.0; +} + +.jfx-tool-bar .jfx-decorator-button { + -fx-cursor: head; } .jfx-tool-bar Label { @@ -219,6 +223,26 @@ -jfx-rippler-fill: WHITE; } +.jfx-decorator-button { + -fx-max-width: 35px; + -fx-background-radius: 40px; + -fx-max-height: 35px; + -fx-background-color: transparent; + -jfx-toggle-color: rgba(128, 128, 255, 0.2); + -jfx-untoggle-color: transparent; +} + +.jfx-decorator-button .icon { + -fx-fill: rgb(204.0, 204.0, 51.0); + -fx-padding: 0.0; +} + +.jfx-decorator-button .jfx-rippler { + -jfx-rippler-fill: white; + -jfx-mask-type: CIRCLE; + -fx-padding: 0.0; +} + .option-list-view { -fx-pref-width: 160.0px; -fx-background-color: WHITE; @@ -617,7 +641,7 @@ -jfx-mask-type: CIRCLE; } -.toggle-icon2, .toggle-icon3 { +.toggle-icon2, .toggle-icon3, .jfx-decorator-button { -fx-pref-width: 50px; -fx-background-radius: 50px; -fx-pref-height: 50px; @@ -805,16 +829,21 @@ *******************************************************************************/ .jfx-decorator { - -fx-decorator-color: derive(#5264AE, -20%); + -fx-decorator-color: derive(#5264AE, 0); } .jfx-decorator .jfx-decorator-buttons-container { -fx-background-color: -fx-decorator-color; } -.jfx-decorator .resize-border { - -fx-border-color: -fx-decorator-color; - -fx-border-width: 0 4 4 4; +.resize-border { + -fx-border-color: #5264AE; + -fx-border-width: 0 2 2 2; +} + +.debug-border { + -fx-border-color: red; + -fx-border-width: 1; } /******************************************************************************* diff --git a/HMCL/src/main/resources/assets/fxml/decorator.fxml b/HMCL/src/main/resources/assets/fxml/decorator.fxml index 485602d81..f595d8eac 100644 --- a/HMCL/src/main/resources/assets/fxml/decorator.fxml +++ b/HMCL/src/main/resources/assets/fxml/decorator.fxml @@ -4,53 +4,117 @@ - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + onMouseReleased="#onMouseReleased" + onMouseDragged="#onMouseDragged" + onMouseMoved="#onMouseMoved"> + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + +
+
+ - -
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ \ No newline at end of file diff --git a/HMCL/src/main/resources/assets/fxml/main.fxml b/HMCL/src/main/resources/assets/fxml/main.fxml index 9499393df..9fde666a3 100644 --- a/HMCL/src/main/resources/assets/fxml/main.fxml +++ b/HMCL/src/main/resources/assets/fxml/main.fxml @@ -1,9 +1,7 @@ - - - - - - -
- - - - - - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/HMCL/src/main/resources/assets/svg/plus-black.fxml b/HMCL/src/main/resources/assets/svg/plus-black.fxml new file mode 100644 index 000000000..e28cf0728 --- /dev/null +++ b/HMCL/src/main/resources/assets/svg/plus-black.fxml @@ -0,0 +1,2 @@ + + diff --git a/HMCL/src/main/resources/assets/svg/refresh-black.fxml b/HMCL/src/main/resources/assets/svg/refresh-black.fxml new file mode 100644 index 000000000..72c17f472 --- /dev/null +++ b/HMCL/src/main/resources/assets/svg/refresh-black.fxml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.kt b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.kt index b1a0a7132..662e7f5a9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.kt +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/CoupleTask.kt @@ -30,7 +30,7 @@ private class CoupleTask(private val pred: P, private val succ: Task.(P } } -infix fun T.then(b: Task): Task = CoupleTask(this, { b }, true) +infix fun Task.then(b: Task): Task = CoupleTask(this, { b }, true) /** * @param b A runnable that decides what to do next, You can also do something here. diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.kt b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.kt index f9980c06a..528ce2496 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.kt +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FileDownloadTask.kt @@ -33,7 +33,7 @@ import java.net.URL import java.math.BigInteger import java.util.logging.Level -class FileDownloadTask(val url: URL, val file: File, val hash: String? = null, val retry: Int = 5, val proxy: Proxy = Proxy.NO_PROXY): Task() { +class FileDownloadTask @JvmOverloads constructor(val url: URL, val file: File, val hash: String? = null, val retry: Int = 5, val proxy: Proxy = Proxy.NO_PROXY): Task() { override val scheduler: Scheduler = Scheduler.IO_THREAD var onFailed = EventManager>() diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.kt b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.kt index 55c3bef56..fa9cf9d5d 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.kt +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.kt @@ -25,7 +25,7 @@ import java.net.Proxy import java.net.URL import java.nio.charset.Charset -class GetTask(val url: URL, val encoding: Charset = Charsets.UTF_8, private val retry: Int = 5, private val proxy: Proxy = Proxy.NO_PROXY): TaskResult() { +class GetTask @JvmOverloads constructor(val url: URL, val encoding: Charset = Charsets.UTF_8, private val retry: Int = 5, private val proxy: Proxy = Proxy.NO_PROXY): TaskResult() { override val scheduler: Scheduler = Scheduler.IO_THREAD override fun execute() { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Scheduler.kt b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Scheduler.kt index a215d326f..17e0640d3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Scheduler.kt +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Scheduler.kt @@ -18,38 +18,51 @@ package org.jackhuang.hmcl.task import javafx.application.Platform -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors -import java.util.concurrent.Future +import java.util.concurrent.* +import java.util.concurrent.atomic.AtomicReference import javax.swing.SwingUtilities interface Scheduler { - fun schedule(block: Runnable): Future<*>? + fun schedule(block: Callable): Future<*>? companion object Schedulers { - val IMMEDIATE = object : Scheduler { - override fun schedule(block: Runnable): Future<*>? { - block.run() - return null - } - } - val JAVAFX: Scheduler = object : Scheduler { - override fun schedule(block: Runnable): Future<*>? { - Platform.runLater(block) - return null - } - } - val SWING: Scheduler = object : Scheduler { - override fun schedule(block: Runnable): Future<*>? { - SwingUtilities.invokeLater(block) - return null + val JAVAFX: Scheduler = SchedulerImpl(Platform::runLater) + val SWING: Scheduler = SchedulerImpl(SwingUtilities::invokeLater) + private class SchedulerImpl(val executor: (() -> Unit) -> Unit) : Scheduler { + override fun schedule(block: Callable): Future<*>? { + val latch = CountDownLatch(1) + val wrapper = AtomicReference() + executor { + try { + block.call() + } catch (e: Exception) { + wrapper.set(e) + } finally { + latch.countDown() + } + } + return object : Future { + override fun get(timeout: Long, unit: TimeUnit) { + latch.await(timeout, unit) + val e = wrapper.get() + if (e != null) throw ExecutionException(e) + } + override fun get() { + latch.await() + val e = wrapper.get() + if (e != null) throw ExecutionException(e) + } + override fun isDone() = latch.count == 0L + override fun isCancelled() = false + override fun cancel(mayInterruptIfRunning: Boolean) = false + } } } val NEW_THREAD: Scheduler = object : Scheduler { - override fun schedule(block: Runnable) = CACHED_EXECUTOR.submit(block) + override fun schedule(block: Callable) = CACHED_EXECUTOR.submit(block) } val IO_THREAD: Scheduler = object : Scheduler { - override fun schedule(block: Runnable) = IO_EXECUTOR.submit(block) + override fun schedule(block: Callable) = IO_EXECUTOR.submit(block) } val DEFAULT = NEW_THREAD private val CACHED_EXECUTOR: ExecutorService by lazy { @@ -57,11 +70,11 @@ interface Scheduler { } private val IO_EXECUTOR: ExecutorService by lazy { - Executors.newFixedThreadPool(6, { r: Runnable -> + Executors.newFixedThreadPool(6) { r: Runnable -> val thread: Thread = Executors.defaultThreadFactory().newThread(r) thread.isDaemon = true thread - }) + } } fun shutdown() { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTask.kt b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTask.kt index 33a8d3f79..e17ed1743 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTask.kt +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/SimpleTask.kt @@ -17,7 +17,7 @@ */ package org.jackhuang.hmcl.task -internal class SimpleTask(private val runnable: () -> Unit, override val scheduler: Scheduler = Scheduler.DEFAULT) : Task() { +internal class SimpleTask @JvmOverloads constructor(private val runnable: () -> Unit, override val scheduler: Scheduler = Scheduler.DEFAULT) : Task() { override fun execute() { runnable() } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.kt b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.kt index 79e463a8d..f6da3601b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.kt +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/Task.kt @@ -17,7 +17,9 @@ */ package org.jackhuang.hmcl.task +import javafx.beans.property.ReadOnlyDoubleProperty import javafx.beans.property.ReadOnlyDoubleWrapper +import javafx.beans.property.ReadOnlyStringProperty import javafx.beans.property.ReadOnlyStringWrapper import org.jackhuang.hmcl.event.EventManager import org.jackhuang.hmcl.util.* @@ -69,19 +71,23 @@ abstract class Task { protected open val progressInterval = 1000L private var lastTime = Long.MIN_VALUE private val progressUpdate = AtomicReference() - val progressProperty = ReadOnlyDoubleWrapper(this, "progress", 0.0) + private val progressPropertyImpl = ReadOnlyDoubleWrapper(this, "progress", 0.0) + val progressProperty: ReadOnlyDoubleProperty = progressPropertyImpl.readOnlyProperty + @JvmName("progressProperty") get protected fun updateProgress(progress: Int, total: Int) = updateProgress(1.0 * progress / total) protected fun updateProgress(progress: Double) { val now = System.currentTimeMillis() if (now - lastTime >= progressInterval) { - progressProperty.updateAsync(progress, progressUpdate) + progressPropertyImpl.updateAsync(progress, progressUpdate) lastTime = now } } private val messageUpdate = AtomicReference() - val messageProperty = ReadOnlyStringWrapper(this, "message", null) - protected fun updateMessage(newMessage: String) = messageProperty.updateAsync(newMessage, messageUpdate) + private val messagePropertyImpl = ReadOnlyStringWrapper(this, "message", null) + val messageProperty: ReadOnlyStringProperty = messagePropertyImpl.readOnlyProperty + @JvmName("messageProperty") get + protected fun updateMessage(newMessage: String) = messagePropertyImpl.updateAsync(newMessage, messageUpdate) val onDone = EventManager() @@ -97,11 +103,11 @@ abstract class Task { } private val subTaskRunnable = { task: Task -> - this.messageProperty.bind(task.messageProperty) - this.progressProperty.bind(task.progressProperty) + this.messagePropertyImpl.bind(task.messagePropertyImpl) + this.progressPropertyImpl.bind(task.progressPropertyImpl) task.run() - this.messageProperty.unbind() - this.progressProperty.unbind() + this.messagePropertyImpl.unbind() + this.progressPropertyImpl.unbind() } fun executor() = TaskExecutor().submit(this) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.kt b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.kt index 92c834c78..73dc45ef0 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.kt +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/task/TaskExecutor.kt @@ -52,7 +52,7 @@ class TaskExecutor() { while (!taskQueue.isEmpty() && !canceled) { val task = taskQueue.poll() if (task != null) { - val future = task.scheduler.schedule(Runnable { executeTask(task) }) + val future = task.scheduler.schedule(Callable { executeTask(task); Unit }) try { future?.get() } catch (e: InterruptedException) { @@ -142,8 +142,8 @@ class TaskExecutor() { return flag } - private inner class Invoker(val task: Task, val latch: CountDownLatch, val boolean: AtomicBoolean): Runnable { - override fun run() { + private inner class Invoker(val task: Task, val latch: CountDownLatch, val boolean: AtomicBoolean): Callable { + override fun call() { try { Thread.currentThread().name = task.title if (!executeTask(task)) diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Constants.kt b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Constants.kt index a801bf97d..24d75e1ef 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Constants.kt +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Constants.kt @@ -15,6 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see {http://www.gnu.org/licenses/}. */ +@file:JvmName("Constants") package org.jackhuang.hmcl.util import javafx.application.Platform diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.kt b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.kt index 948bc6d72..257fd6258 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.kt +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/Logging.kt @@ -15,6 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see {http://www.gnu.org/licenses/}. */ +@file:JvmName("HMCLog") package org.jackhuang.hmcl.util import java.io.ByteArrayOutputStream diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ReflectionHelper.kt b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ReflectionHelper.kt index 2039af8ce..09f3937c3 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ReflectionHelper.kt +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ReflectionHelper.kt @@ -23,7 +23,6 @@ import java.lang.reflect.Method import java.security.PrivilegedExceptionAction import java.security.AccessController - object ReflectionHelper { private lateinit var unsafe: Unsafe diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StreamPump.kt b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StreamPump.kt index 1414e83aa..c59bd0923 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StreamPump.kt +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/StreamPump.kt @@ -21,7 +21,7 @@ import java.io.IOException import java.io.InputStream import java.util.logging.Level -internal class StreamPump( +internal class StreamPump @JvmOverloads constructor( val inputStream: InputStream, val callback: (String) -> Unit = {} ) : Runnable { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ZipUtils.kt b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ZipUtils.kt index 6878f4697..317e118ac 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ZipUtils.kt +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/ZipUtils.kt @@ -23,13 +23,6 @@ import java.io.IOException import java.util.zip.ZipOutputStream import java.util.zip.ZipInputStream - - -@Throws(IOException::class) -fun zip(src: String, destZip: String) { - zip(File(src), File(destZip), null) -} - /** * 功能:把 src 目录下的所有文件进行 zip 格式的压缩,保存为指定 zip 文件 @@ -43,8 +36,9 @@ fun zip(src: String, destZip: String) { * * * @throws java.io.IOException 压缩失败或无法读取 */ +@JvmOverloads @Throws(IOException::class) -fun zip(src: File, destZip: File, pathNameCallback: ((String, Boolean) -> String?)?) { +fun zip(src: File, destZip: File, pathNameCallback: ((String, Boolean) -> String?)? = null) { ZipOutputStream(destZip.outputStream()).use { zos -> val basePath: String if (src.isDirectory) @@ -103,11 +97,6 @@ private fun zipFile(src: File, } } -@Throws(IOException::class) -fun unzip(zip: File, dest: File) { - unzip(zip, dest, null, true) -} - /** * 将文件压缩成zip文件 @@ -121,8 +110,9 @@ fun unzip(zip: File, dest: File) { * * * @throws java.io.IOException 解压失败或无法写入 */ +@JvmOverloads @Throws(IOException::class) -fun unzip(zip: File, dest: File, callback: ((String) -> Boolean)?, ignoreExistsFile: Boolean) { +fun unzip(zip: File, dest: File, callback: ((String) -> Boolean)? = null, ignoreExistsFile: Boolean = true) { val buf = ByteArray(1024) dest.mkdirs() ZipInputStream(zip.inputStream()).use { zipFile -> diff --git a/lib/JFoenix.jar b/lib/JFoenix.jar index 07caab01d..d837cecc4 100644 Binary files a/lib/JFoenix.jar and b/lib/JFoenix.jar differ