mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-09 20:06:39 -04:00
Scheduler JavaFX and Swing now have Future
This commit is contained in:
parent
736a8c1b30
commit
f1ffa5ca03
@ -34,12 +34,14 @@ object Controllers {
|
|||||||
lateinit var versionController: VersionController
|
lateinit var versionController: VersionController
|
||||||
val versionPane: Pane = loadPane("version")
|
val versionPane: Pane = loadPane("version")
|
||||||
|
|
||||||
|
lateinit var decorator: Decorator
|
||||||
|
|
||||||
fun initialize(stage: Stage) {
|
fun initialize(stage: Stage) {
|
||||||
this.stage = stage
|
this.stage = stage
|
||||||
|
|
||||||
val decorator = Decorator(stage, mainPane, max = false)
|
val decorator = Decorator(stage, mainPane, max = false)
|
||||||
// Let root pane fix window size.
|
// Let root pane fix window size.
|
||||||
(mainPane.parent as StackPane).run {
|
with(mainPane.parent as StackPane) {
|
||||||
mainPane.prefWidthProperty().bind(widthProperty())
|
mainPane.prefWidthProperty().bind(widthProperty())
|
||||||
mainPane.prefHeightProperty().bind(heightProperty())
|
mainPane.prefHeightProperty().bind(heightProperty())
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
package org.jackhuang.hmcl.ui
|
package org.jackhuang.hmcl.ui
|
||||||
|
|
||||||
import com.jfoenix.controls.JFXButton
|
import com.jfoenix.controls.JFXButton
|
||||||
|
import com.jfoenix.effects.JFXDepthManager
|
||||||
import com.jfoenix.svg.SVGGlyph
|
import com.jfoenix.svg.SVGGlyph
|
||||||
import javafx.animation.*
|
import javafx.animation.*
|
||||||
import javafx.application.Platform
|
import javafx.application.Platform
|
||||||
@ -31,6 +32,7 @@ import javafx.geometry.Bounds
|
|||||||
import javafx.geometry.Insets
|
import javafx.geometry.Insets
|
||||||
import javafx.scene.Cursor
|
import javafx.scene.Cursor
|
||||||
import javafx.scene.Node
|
import javafx.scene.Node
|
||||||
|
import javafx.scene.control.Label
|
||||||
import javafx.scene.control.Tooltip
|
import javafx.scene.control.Tooltip
|
||||||
import javafx.scene.input.MouseEvent
|
import javafx.scene.input.MouseEvent
|
||||||
import javafx.scene.layout.*
|
import javafx.scene.layout.*
|
||||||
@ -39,8 +41,11 @@ import javafx.scene.shape.Rectangle
|
|||||||
import javafx.stage.Screen
|
import javafx.stage.Screen
|
||||||
import javafx.stage.Stage
|
import javafx.stage.Stage
|
||||||
import javafx.stage.StageStyle
|
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 xOffset: Double = 0.0
|
||||||
private var yOffset: Double = 0.0
|
private var yOffset: Double = 0.0
|
||||||
private var newX: 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 contentPlaceHolder: StackPane
|
||||||
@FXML lateinit var titleContainer: BorderPane
|
@FXML lateinit var titleContainer: BorderPane
|
||||||
@FXML lateinit var buttonsContainer: HBox
|
@FXML lateinit var buttonsContainer: HBox
|
||||||
private val onCloseButtonAction: ObjectProperty<Runnable>
|
@FXML lateinit var backNavButton: JFXButton
|
||||||
private val customMaximize: BooleanProperty
|
@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<Runnable> = 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 maximized: Boolean = false
|
||||||
private var originalBox: BoundingBox? = null
|
private var originalBox: BoundingBox? = null
|
||||||
private var maximizedBox: BoundingBox? = null
|
private var maximizedBox: BoundingBox? = null
|
||||||
@FXML lateinit var btnMin: JFXButton
|
@FXML lateinit var btnMin: JFXButton
|
||||||
@FXML lateinit var btnMax: JFXButton
|
@FXML lateinit var btnMax: JFXButton
|
||||||
@FXML lateinit var btnClose: JFXButton
|
@FXML lateinit var btnClose: JFXButton
|
||||||
private val minus: 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)
|
||||||
private val resizeMax: SVGGlyph
|
.apply { setSize(12.0, 2.0); translateY = 4.0 }
|
||||||
private val resizeMin: SVGGlyph
|
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)
|
||||||
private val close: SVGGlyph
|
.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 {
|
init {
|
||||||
loadFXML("/assets/fxml/decorator.fxml")
|
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)
|
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
|
btnClose.graphic = close
|
||||||
btnMin.graphic = minus
|
btnMin.graphic = minus
|
||||||
this.btnMax.graphic = resizeMax
|
btnMax.graphic = resizeMax
|
||||||
|
|
||||||
buttonsContainer.background = Background(*arrayOf(BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY)))
|
buttonsContainer.background = Background(*arrayOf(BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY)))
|
||||||
titleContainer.addEventHandler(MouseEvent.MOUSE_CLICKED) { mouseEvent ->
|
titleContainer.addEventHandler(MouseEvent.MOUSE_CLICKED) { mouseEvent ->
|
||||||
if (mouseEvent.clickCount == 2) {
|
if (mouseEvent.clickCount == 2) {
|
||||||
this.btnMax.fire()
|
btnMax.fire()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!min) buttonsContainer.children.remove(btnMin)
|
if (!min) buttonsContainer.children.remove(btnMin)
|
||||||
|
|
||||||
if (!max) buttonsContainer.children.remove(btnMax)
|
if (!max) buttonsContainer.children.remove(btnMax)
|
||||||
|
|
||||||
titleContainer.addEventHandler(MouseEvent.MOUSE_ENTERED) { enter -> this.allowMove = true }
|
JFXDepthManager.setDepth(titleContainer, 1)
|
||||||
titleContainer.addEventHandler(MouseEvent.MOUSE_EXITED) { enter ->
|
titleContainer.addEventHandler(MouseEvent.MOUSE_ENTERED) { this.allowMove = true }
|
||||||
if (!this.isDragging) {
|
titleContainer.addEventHandler(MouseEvent.MOUSE_EXITED) { if (!this.isDragging) this.allowMove = false }
|
||||||
this.allowMove = false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
this.contentPlaceHolder.children.add(node)
|
this.contentPlaceHolder.children.add(node)
|
||||||
(node as Region).setMinSize(0.0, 0.0)
|
(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()
|
val clip = Rectangle()
|
||||||
clip.widthProperty().bind(node.widthProperty())
|
clip.widthProperty().bind(node.widthProperty())
|
||||||
clip.heightProperty().bind(node.heightProperty())
|
clip.heightProperty().bind(node.heightProperty())
|
||||||
@ -127,7 +128,7 @@ class Decorator @JvmOverloads constructor(private val primaryStage: Stage, node:
|
|||||||
val x = mouseEvent.x
|
val x = mouseEvent.x
|
||||||
val y = mouseEvent.y
|
val y = mouseEvent.y
|
||||||
val boundsInParent = this.boundsInParent
|
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()
|
val borderWidth = this.contentPlaceHolder.snappedLeftInset()
|
||||||
if (this.isRightEdge(x, y, boundsInParent)) {
|
if (this.isRightEdge(x, y, boundsInParent)) {
|
||||||
if (y < borderWidth) {
|
if (y < borderWidth) {
|
||||||
@ -274,7 +275,7 @@ class Decorator @JvmOverloads constructor(private val primaryStage: Stage, node:
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onClose() {
|
fun onClose() {
|
||||||
(this.onCloseButtonAction.get() as Runnable).run()
|
this.onCloseButtonAction.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateInitMouseValues(mouseEvent: MouseEvent) {
|
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) {
|
fun setMaximized(maximized: Boolean) {
|
||||||
if (this.maximized != maximized) {
|
if (this.maximized != maximized) {
|
||||||
Platform.runLater { this.btnMax.fire() }
|
Platform.runLater { this.btnMax.fire() }
|
||||||
|
@ -106,6 +106,8 @@ fun setOverflowHidden(node: Pane) {
|
|||||||
node.clip = rectangle
|
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-components.css").toExternalForm(),
|
||||||
Controllers::class.java.getResource("/assets/css/jfoenix-main-demo.css").toExternalForm())
|
Controllers::class.java.getResource("/assets/css/jfoenix-main-demo.css").toExternalForm())
|
@ -212,7 +212,7 @@
|
|||||||
|
|
||||||
.jfx-tool-bar HBox {
|
.jfx-tool-bar HBox {
|
||||||
-fx-alignment: center;
|
-fx-alignment: center;
|
||||||
-fx-spacing: 25;
|
/* -fx-spacing: 25;*/
|
||||||
-fx-padding: 0 10;
|
-fx-padding: 0 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,8 +199,12 @@
|
|||||||
|
|
||||||
.jfx-tool-bar HBox {
|
.jfx-tool-bar HBox {
|
||||||
-fx-alignment: center;
|
-fx-alignment: center;
|
||||||
-fx-spacing: 25.0;
|
/* -fx-spacing: 25.0;*/
|
||||||
-fx-padding: 0.0 10.0;
|
-fx-padding: 0.0 5.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jfx-tool-bar .jfx-decorator-button {
|
||||||
|
-fx-cursor: head;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jfx-tool-bar Label {
|
.jfx-tool-bar Label {
|
||||||
@ -219,6 +223,26 @@
|
|||||||
-jfx-rippler-fill: WHITE;
|
-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 {
|
.option-list-view {
|
||||||
-fx-pref-width: 160.0px;
|
-fx-pref-width: 160.0px;
|
||||||
-fx-background-color: WHITE;
|
-fx-background-color: WHITE;
|
||||||
@ -617,7 +641,7 @@
|
|||||||
-jfx-mask-type: CIRCLE;
|
-jfx-mask-type: CIRCLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toggle-icon2, .toggle-icon3 {
|
.toggle-icon2, .toggle-icon3, .jfx-decorator-button {
|
||||||
-fx-pref-width: 50px;
|
-fx-pref-width: 50px;
|
||||||
-fx-background-radius: 50px;
|
-fx-background-radius: 50px;
|
||||||
-fx-pref-height: 50px;
|
-fx-pref-height: 50px;
|
||||||
@ -805,16 +829,21 @@
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
.jfx-decorator {
|
.jfx-decorator {
|
||||||
-fx-decorator-color: derive(#5264AE, -20%);
|
-fx-decorator-color: derive(#5264AE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.jfx-decorator .jfx-decorator-buttons-container {
|
.jfx-decorator .jfx-decorator-buttons-container {
|
||||||
-fx-background-color: -fx-decorator-color;
|
-fx-background-color: -fx-decorator-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jfx-decorator .resize-border {
|
.resize-border {
|
||||||
-fx-border-color: -fx-decorator-color;
|
-fx-border-color: #5264AE;
|
||||||
-fx-border-width: 0 4 4 4;
|
-fx-border-width: 0 2 2 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.debug-border {
|
||||||
|
-fx-border-color: red;
|
||||||
|
-fx-border-width: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -4,53 +4,117 @@
|
|||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
<?import com.jfoenix.controls.JFXButton?>
|
<?import com.jfoenix.controls.JFXButton?>
|
||||||
<?import javafx.scene.Cursor?>
|
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import java.lang.String?>
|
<?import java.lang.String?>
|
||||||
|
<?import javafx.scene.shape.Rectangle?>
|
||||||
|
<?import com.jfoenix.controls.JFXComboBox?>
|
||||||
|
<?import com.jfoenix.controls.JFXListView?>
|
||||||
|
<?import com.jfoenix.controls.JFXListCell?>
|
||||||
<fx:root xmlns="http://javafx.com/javafx"
|
<fx:root xmlns="http://javafx.com/javafx"
|
||||||
type="VBox"
|
type="GridPane"
|
||||||
xmlns:fx="http://javafx.com/fxml"
|
xmlns:fx="http://javafx.com/fxml"
|
||||||
styleClass="jfx-decorator"
|
|
||||||
pickOnBounds="false"
|
pickOnBounds="false"
|
||||||
onMouseReleased="#onMouseReleased"
|
onMouseReleased="#onMouseReleased"
|
||||||
onMouseDragged="#onMouseDragged"
|
onMouseDragged="#onMouseDragged"
|
||||||
onMouseMoved="#onMouseMoved">
|
onMouseMoved="#onMouseMoved">
|
||||||
|
<styleClass>
|
||||||
<BorderPane fx:id="titleContainer" styleClass="jfx-decorator-buttons-container" pickOnBounds="false">
|
<String fx:value="jfx-decorator" />
|
||||||
<left>
|
<String fx:value="resize-border" />
|
||||||
<HBox fx:id="titleWrapper" alignment="CENTER_LEFT" style="-fx-padding: 15;">
|
</styleClass>
|
||||||
<Label text="Hello Minecraft! Launcher" mouseTransparent="false" style="-fx-background-color: transparent; -fx-text-fill: white; -fx-font-size: 15px;" />
|
<columnConstraints>
|
||||||
</HBox>
|
<ColumnConstraints prefWidth="200" />
|
||||||
</left>
|
<ColumnConstraints hgrow="ALWAYS" />
|
||||||
<right>
|
</columnConstraints>
|
||||||
<HBox fx:id="buttonsContainer" styleClass="jfx-decorator-buttons-container" alignment="CENTER_RIGHT" minWidth="180">
|
<rowConstraints>
|
||||||
<padding>
|
<RowConstraints />
|
||||||
<Insets topRightBottomLeft="4.0" />
|
<RowConstraints vgrow="ALWAYS" />
|
||||||
</padding>
|
</rowConstraints>
|
||||||
<JFXButton fx:id="btnMin" styleClass="jfx-decorator-button" ripplerFill="white" onAction="#onMin">
|
<StackPane GridPane.rowIndex="1" GridPane.columnIndex="0" VBox.vgrow="ALWAYS" styleClass="jfx-decorator-content-container">
|
||||||
<cursor>
|
<BorderPane prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
|
||||||
<Cursor fx:constant="HAND" />
|
<center>
|
||||||
</cursor>
|
<ScrollPane fitToHeight="true" fitToWidth="true">
|
||||||
</JFXButton>
|
<VBox fx:id="leftPane">
|
||||||
<JFXButton fx:id="btnMax" styleClass="jfx-decorator-button" ripplerFill="white" onAction="#onMax">
|
</VBox>
|
||||||
<cursor>
|
</ScrollPane>
|
||||||
<Cursor fx:constant="HAND" />
|
</center>
|
||||||
</cursor>
|
<bottom>
|
||||||
</JFXButton>
|
<BorderPane fx:id="menuBottomBar">
|
||||||
<JFXButton fx:id="btnClose" styleClass="jfx-decorator-button" ripplerFill="white" onAction="#onClose">
|
<left>
|
||||||
<cursor>
|
<JFXButton fx:id="refreshMenuButton" styleClass="toggle-icon3">
|
||||||
<Cursor fx:constant="HAND" />
|
<graphic>
|
||||||
</cursor>
|
<fx:include source="/assets/svg/refresh-black.fxml"/>
|
||||||
</JFXButton>
|
</graphic></JFXButton>
|
||||||
</HBox>
|
</left>
|
||||||
</right>
|
<right>
|
||||||
</BorderPane>
|
<JFXButton fx:id="addMenuButton" styleClass="toggle-icon3">
|
||||||
|
<graphic>
|
||||||
<StackPane fx:id="contentPlaceHolder" styleClass="jfx-decorator-content-container resize-border" minWidth="0" minHeight="0" VBox.vgrow="ALWAYS">
|
<fx:include source="/assets/svg/plus-black.fxml"/>
|
||||||
|
</graphic></JFXButton>
|
||||||
|
</right>
|
||||||
|
</BorderPane>
|
||||||
|
</bottom>
|
||||||
|
</BorderPane>
|
||||||
|
</StackPane>
|
||||||
|
<StackPane GridPane.rowIndex="1" GridPane.columnIndex="1" fx:id="contentPlaceHolder" styleClass="jfx-decorator-content-container" minWidth="0" minHeight="0" VBox.vgrow="ALWAYS">
|
||||||
<styleClass>
|
<styleClass>
|
||||||
<String fx:value="jfx-decorator-content-container" />
|
<String fx:value="jfx-decorator-content-container" />
|
||||||
<String fx:value="resize-border" />
|
|
||||||
</styleClass>
|
</styleClass>
|
||||||
<!-- Node -->
|
<!-- Node -->
|
||||||
</StackPane>
|
</StackPane>
|
||||||
</fx:root>
|
<BorderPane GridPane.rowIndex="0" GridPane.columnIndex="0" GridPane.columnSpan="2" fx:id="titleContainer" styleClass="jfx-tool-bar" pickOnBounds="false">
|
||||||
|
<left>
|
||||||
|
<HBox minWidth="200" fx:id="titleWrapper" alignment="CENTER_LEFT">
|
||||||
|
<Label text="Hello Minecraft! Launcher" mouseTransparent="false" style="-fx-background-color: transparent; -fx-text-fill: white; -fx-font-size: 15px;" />
|
||||||
|
</HBox>
|
||||||
|
</left>
|
||||||
|
<center>
|
||||||
|
<BorderPane fx:id="navBar">
|
||||||
|
<left>
|
||||||
|
<HBox fx:id="navLeft" alignment="CENTER_LEFT" style="-fx-padding: 0;">
|
||||||
|
<Rectangle height="${navBar.height}" width="1" fill="gray" />
|
||||||
|
<JFXButton fx:id="backNavButton" maxHeight="20" styleClass="toggle-icon3">
|
||||||
|
<graphic>
|
||||||
|
<fx:include source="/assets/svg/arrow-left.fxml"/>
|
||||||
|
</graphic>
|
||||||
|
</JFXButton>
|
||||||
|
<Label fx:id="titleLabel" style="-fx-text-fill:WHITE; -fx-font-size: 15;"/>
|
||||||
|
</HBox>
|
||||||
|
</left>
|
||||||
|
<right>
|
||||||
|
<HBox fx:id="navRight" alignment="CENTER_LEFT">
|
||||||
|
<JFXButton fx:id="refreshNavButton" maxHeight="20" styleClass="toggle-icon3" disable="true">
|
||||||
|
<graphic>
|
||||||
|
<fx:include source="/assets/svg/refresh.fxml"/>
|
||||||
|
</graphic>
|
||||||
|
<StackPane.margin>
|
||||||
|
<Insets left="20"/>
|
||||||
|
</StackPane.margin>
|
||||||
|
</JFXButton>
|
||||||
|
<JFXButton fx:id="closeNavButton" maxHeight="20" styleClass="toggle-icon3">
|
||||||
|
<graphic>
|
||||||
|
<fx:include source="/assets/svg/close.fxml"/>
|
||||||
|
</graphic>
|
||||||
|
<StackPane.margin>
|
||||||
|
<Insets left="20"/>
|
||||||
|
</StackPane.margin>
|
||||||
|
</JFXButton>
|
||||||
|
<Rectangle height="${navBar.height}" width="1" fill="gray" />
|
||||||
|
</HBox>
|
||||||
|
</right>
|
||||||
|
</BorderPane>
|
||||||
|
</center>
|
||||||
|
<right>
|
||||||
|
<HBox fx:id="buttonsContainer" style="-fx-background-color: transparent;" alignment="CENTER_RIGHT">
|
||||||
|
<padding>
|
||||||
|
<Insets topRightBottomLeft="4.0" />
|
||||||
|
</padding>
|
||||||
|
<JFXButton fx:id="btnMin" styleClass="jfx-decorator-button" ripplerFill="white" onAction="#onMin">
|
||||||
|
</JFXButton>
|
||||||
|
<JFXButton fx:id="btnMax" styleClass="jfx-decorator-button" ripplerFill="white" onAction="#onMax">
|
||||||
|
</JFXButton>
|
||||||
|
<JFXButton fx:id="btnClose" styleClass="jfx-decorator-button" ripplerFill="white" onAction="#onClose">
|
||||||
|
</JFXButton>
|
||||||
|
</HBox>
|
||||||
|
</right>
|
||||||
|
</BorderPane>
|
||||||
|
</fx:root>
|
@ -1,9 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import javafx.scene.control.*?>
|
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
<?import com.jfoenix.controls.*?>
|
<?import com.jfoenix.controls.*?>
|
||||||
<?import javafx.geometry.Insets?>
|
|
||||||
<BorderPane
|
<BorderPane
|
||||||
maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
|
maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity"
|
||||||
fx:controller="org.jackhuang.hmcl.ui.MainController"
|
fx:controller="org.jackhuang.hmcl.ui.MainController"
|
||||||
@ -13,59 +11,7 @@
|
|||||||
<StackPane fx:id="page" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
|
<StackPane fx:id="page" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
|
||||||
</center>
|
</center>
|
||||||
<left>
|
<left>
|
||||||
<BorderPane prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
|
|
||||||
<top>
|
|
||||||
<JFXComboBox fx:id="comboProfiles" prefWidth="150.0" BorderPane.alignment="CENTER" />
|
|
||||||
</top>
|
|
||||||
<center>
|
|
||||||
<StackPane>
|
|
||||||
<JFXListView fx:id="listVersions" styleClass="mylistview" style="-fx-background-color: #F1F1F1;" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
|
|
||||||
<AnchorPane pickOnBounds="false">
|
|
||||||
<JFXButton AnchorPane.bottomAnchor="16" AnchorPane.rightAnchor="16" buttonType="RAISED" prefWidth="40" prefHeight="40" style="-fx-text-fill:WHITE;-fx-background-color:#5264AE;-fx-font-size:14px;-fx-background-radius: 80px;">
|
|
||||||
<graphic>
|
|
||||||
<fx:include source="/assets/svg/plus.fxml" />
|
|
||||||
</graphic>
|
|
||||||
</JFXButton>
|
|
||||||
</AnchorPane>
|
|
||||||
</StackPane>
|
|
||||||
</center>
|
|
||||||
</BorderPane>
|
|
||||||
</left>
|
</left>
|
||||||
<top>
|
|
||||||
<JFXToolbar fx:id="toolbar" styleClass="jfx-tool-bar">
|
|
||||||
<leftItems>
|
|
||||||
<JFXButton fx:id="closeButton" maxHeight="20" styleClass="toggle-icon3"
|
|
||||||
StackPane.alignment="CENTER_RIGHT">
|
|
||||||
<graphic>
|
|
||||||
<fx:include source="/assets/svg/close.fxml"/>
|
|
||||||
</graphic>
|
|
||||||
<StackPane.margin>
|
|
||||||
<Insets left="20"/>
|
|
||||||
</StackPane.margin>
|
|
||||||
</JFXButton>
|
|
||||||
<JFXButton fx:id="backButton" maxHeight="20" styleClass="toggle-icon3"
|
|
||||||
StackPane.alignment="CENTER_LEFT">
|
|
||||||
<graphic>
|
|
||||||
<fx:include source="/assets/svg/arrow-left.fxml"/>
|
|
||||||
</graphic>
|
|
||||||
</JFXButton>
|
|
||||||
<Label fx:id="titleLabel" style="-fx-text-fill:WHITE; -fx-font-size: 15;"
|
|
||||||
StackPane.alignment="CENTER_LEFT"/>
|
|
||||||
</leftItems>
|
|
||||||
<rightItems>
|
|
||||||
<JFXButton fx:id="refreshButton" maxHeight="20" styleClass="toggle-icon3" disable="true"
|
|
||||||
StackPane.alignment="CENTER_RIGHT">
|
|
||||||
<graphic>
|
|
||||||
<fx:include source="/assets/svg/refresh.fxml"/>
|
|
||||||
</graphic>
|
|
||||||
<StackPane.margin>
|
|
||||||
<Insets left="20"/>
|
|
||||||
</StackPane.margin>
|
|
||||||
</JFXButton>
|
|
||||||
</rightItems>
|
|
||||||
</JFXToolbar>
|
|
||||||
|
|
||||||
</top>
|
|
||||||
<bottom>
|
<bottom>
|
||||||
<BorderPane prefHeight="50.0" prefWidth="200.0" BorderPane.alignment="CENTER">
|
<BorderPane prefHeight="50.0" prefWidth="200.0" BorderPane.alignment="CENTER">
|
||||||
<right>
|
<right>
|
||||||
|
2
HMCL/src/main/resources/assets/svg/plus-black.fxml
Normal file
2
HMCL/src/main/resources/assets/svg/plus-black.fxml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<javafx.scene.shape.SVGPath fill="black" content="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" />
|
2
HMCL/src/main/resources/assets/svg/refresh-black.fxml
Normal file
2
HMCL/src/main/resources/assets/svg/refresh-black.fxml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<javafx.scene.shape.SVGPath fill="black" content="M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z" />
|
@ -30,7 +30,7 @@ private class CoupleTask<P: Task>(private val pred: P, private val succ: Task.(P
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun <T: Task> 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.
|
* @param b A runnable that decides what to do next, You can also do something here.
|
||||||
|
@ -33,7 +33,7 @@ import java.net.URL
|
|||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.util.logging.Level
|
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
|
override val scheduler: Scheduler = Scheduler.IO_THREAD
|
||||||
|
|
||||||
var onFailed = EventManager<FailedEvent<URL>>()
|
var onFailed = EventManager<FailedEvent<URL>>()
|
||||||
|
@ -25,7 +25,7 @@ import java.net.Proxy
|
|||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.charset.Charset
|
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<String>() {
|
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<String>() {
|
||||||
override val scheduler: Scheduler = Scheduler.IO_THREAD
|
override val scheduler: Scheduler = Scheduler.IO_THREAD
|
||||||
|
|
||||||
override fun execute() {
|
override fun execute() {
|
||||||
|
@ -18,38 +18,51 @@
|
|||||||
package org.jackhuang.hmcl.task
|
package org.jackhuang.hmcl.task
|
||||||
|
|
||||||
import javafx.application.Platform
|
import javafx.application.Platform
|
||||||
import java.util.concurrent.ExecutorService
|
import java.util.concurrent.*
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
import java.util.concurrent.Future
|
|
||||||
import javax.swing.SwingUtilities
|
import javax.swing.SwingUtilities
|
||||||
|
|
||||||
interface Scheduler {
|
interface Scheduler {
|
||||||
fun schedule(block: Runnable): Future<*>?
|
fun schedule(block: Callable<Unit>): Future<*>?
|
||||||
|
|
||||||
companion object Schedulers {
|
companion object Schedulers {
|
||||||
val IMMEDIATE = object : Scheduler {
|
val JAVAFX: Scheduler = SchedulerImpl(Platform::runLater)
|
||||||
override fun schedule(block: Runnable): Future<*>? {
|
val SWING: Scheduler = SchedulerImpl(SwingUtilities::invokeLater)
|
||||||
block.run()
|
private class SchedulerImpl(val executor: (() -> Unit) -> Unit) : Scheduler {
|
||||||
return null
|
override fun schedule(block: Callable<Unit>): Future<*>? {
|
||||||
}
|
val latch = CountDownLatch(1)
|
||||||
}
|
val wrapper = AtomicReference<Exception>()
|
||||||
val JAVAFX: Scheduler = object : Scheduler {
|
executor {
|
||||||
override fun schedule(block: Runnable): Future<*>? {
|
try {
|
||||||
Platform.runLater(block)
|
block.call()
|
||||||
return null
|
} catch (e: Exception) {
|
||||||
}
|
wrapper.set(e)
|
||||||
}
|
} finally {
|
||||||
val SWING: Scheduler = object : Scheduler {
|
latch.countDown()
|
||||||
override fun schedule(block: Runnable): Future<*>? {
|
}
|
||||||
SwingUtilities.invokeLater(block)
|
}
|
||||||
return null
|
return object : Future<Unit> {
|
||||||
|
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 {
|
val NEW_THREAD: Scheduler = object : Scheduler {
|
||||||
override fun schedule(block: Runnable) = CACHED_EXECUTOR.submit(block)
|
override fun schedule(block: Callable<Unit>) = CACHED_EXECUTOR.submit(block)
|
||||||
}
|
}
|
||||||
val IO_THREAD: Scheduler = object : Scheduler {
|
val IO_THREAD: Scheduler = object : Scheduler {
|
||||||
override fun schedule(block: Runnable) = IO_EXECUTOR.submit(block)
|
override fun schedule(block: Callable<Unit>) = IO_EXECUTOR.submit(block)
|
||||||
}
|
}
|
||||||
val DEFAULT = NEW_THREAD
|
val DEFAULT = NEW_THREAD
|
||||||
private val CACHED_EXECUTOR: ExecutorService by lazy {
|
private val CACHED_EXECUTOR: ExecutorService by lazy {
|
||||||
@ -57,11 +70,11 @@ interface Scheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val IO_EXECUTOR: ExecutorService by lazy {
|
private val IO_EXECUTOR: ExecutorService by lazy {
|
||||||
Executors.newFixedThreadPool(6, { r: Runnable ->
|
Executors.newFixedThreadPool(6) { r: Runnable ->
|
||||||
val thread: Thread = Executors.defaultThreadFactory().newThread(r)
|
val thread: Thread = Executors.defaultThreadFactory().newThread(r)
|
||||||
thread.isDaemon = true
|
thread.isDaemon = true
|
||||||
thread
|
thread
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shutdown() {
|
fun shutdown() {
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.task
|
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() {
|
override fun execute() {
|
||||||
runnable()
|
runnable()
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.task
|
package org.jackhuang.hmcl.task
|
||||||
|
|
||||||
|
import javafx.beans.property.ReadOnlyDoubleProperty
|
||||||
import javafx.beans.property.ReadOnlyDoubleWrapper
|
import javafx.beans.property.ReadOnlyDoubleWrapper
|
||||||
|
import javafx.beans.property.ReadOnlyStringProperty
|
||||||
import javafx.beans.property.ReadOnlyStringWrapper
|
import javafx.beans.property.ReadOnlyStringWrapper
|
||||||
import org.jackhuang.hmcl.event.EventManager
|
import org.jackhuang.hmcl.event.EventManager
|
||||||
import org.jackhuang.hmcl.util.*
|
import org.jackhuang.hmcl.util.*
|
||||||
@ -69,19 +71,23 @@ abstract class Task {
|
|||||||
protected open val progressInterval = 1000L
|
protected open val progressInterval = 1000L
|
||||||
private var lastTime = Long.MIN_VALUE
|
private var lastTime = Long.MIN_VALUE
|
||||||
private val progressUpdate = AtomicReference<Double>()
|
private val progressUpdate = AtomicReference<Double>()
|
||||||
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: Int, total: Int) = updateProgress(1.0 * progress / total)
|
||||||
protected fun updateProgress(progress: Double) {
|
protected fun updateProgress(progress: Double) {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
if (now - lastTime >= progressInterval) {
|
if (now - lastTime >= progressInterval) {
|
||||||
progressProperty.updateAsync(progress, progressUpdate)
|
progressPropertyImpl.updateAsync(progress, progressUpdate)
|
||||||
lastTime = now
|
lastTime = now
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val messageUpdate = AtomicReference<String>()
|
private val messageUpdate = AtomicReference<String>()
|
||||||
val messageProperty = ReadOnlyStringWrapper(this, "message", null)
|
private val messagePropertyImpl = ReadOnlyStringWrapper(this, "message", null)
|
||||||
protected fun updateMessage(newMessage: String) = messageProperty.updateAsync(newMessage, messageUpdate)
|
val messageProperty: ReadOnlyStringProperty = messagePropertyImpl.readOnlyProperty
|
||||||
|
@JvmName("messageProperty") get
|
||||||
|
protected fun updateMessage(newMessage: String) = messagePropertyImpl.updateAsync(newMessage, messageUpdate)
|
||||||
|
|
||||||
val onDone = EventManager<TaskEvent>()
|
val onDone = EventManager<TaskEvent>()
|
||||||
|
|
||||||
@ -97,11 +103,11 @@ abstract class Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val subTaskRunnable = { task: Task ->
|
private val subTaskRunnable = { task: Task ->
|
||||||
this.messageProperty.bind(task.messageProperty)
|
this.messagePropertyImpl.bind(task.messagePropertyImpl)
|
||||||
this.progressProperty.bind(task.progressProperty)
|
this.progressPropertyImpl.bind(task.progressPropertyImpl)
|
||||||
task.run()
|
task.run()
|
||||||
this.messageProperty.unbind()
|
this.messagePropertyImpl.unbind()
|
||||||
this.progressProperty.unbind()
|
this.progressPropertyImpl.unbind()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun executor() = TaskExecutor().submit(this)
|
fun executor() = TaskExecutor().submit(this)
|
||||||
|
@ -52,7 +52,7 @@ class TaskExecutor() {
|
|||||||
while (!taskQueue.isEmpty() && !canceled) {
|
while (!taskQueue.isEmpty() && !canceled) {
|
||||||
val task = taskQueue.poll()
|
val task = taskQueue.poll()
|
||||||
if (task != null) {
|
if (task != null) {
|
||||||
val future = task.scheduler.schedule(Runnable { executeTask(task) })
|
val future = task.scheduler.schedule(Callable { executeTask(task); Unit })
|
||||||
try {
|
try {
|
||||||
future?.get()
|
future?.get()
|
||||||
} catch (e: InterruptedException) {
|
} catch (e: InterruptedException) {
|
||||||
@ -142,8 +142,8 @@ class TaskExecutor() {
|
|||||||
return flag
|
return flag
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class Invoker(val task: Task, val latch: CountDownLatch, val boolean: AtomicBoolean): Runnable {
|
private inner class Invoker(val task: Task, val latch: CountDownLatch, val boolean: AtomicBoolean): Callable<Unit> {
|
||||||
override fun run() {
|
override fun call() {
|
||||||
try {
|
try {
|
||||||
Thread.currentThread().name = task.title
|
Thread.currentThread().name = task.title
|
||||||
if (!executeTask(task))
|
if (!executeTask(task))
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
*/
|
*/
|
||||||
|
@file:JvmName("Constants")
|
||||||
package org.jackhuang.hmcl.util
|
package org.jackhuang.hmcl.util
|
||||||
|
|
||||||
import javafx.application.Platform
|
import javafx.application.Platform
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
*/
|
*/
|
||||||
|
@file:JvmName("HMCLog")
|
||||||
package org.jackhuang.hmcl.util
|
package org.jackhuang.hmcl.util
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
|
@ -23,7 +23,6 @@ import java.lang.reflect.Method
|
|||||||
import java.security.PrivilegedExceptionAction
|
import java.security.PrivilegedExceptionAction
|
||||||
import java.security.AccessController
|
import java.security.AccessController
|
||||||
|
|
||||||
|
|
||||||
object ReflectionHelper {
|
object ReflectionHelper {
|
||||||
|
|
||||||
private lateinit var unsafe: Unsafe
|
private lateinit var unsafe: Unsafe
|
||||||
|
@ -21,7 +21,7 @@ import java.io.IOException
|
|||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
|
|
||||||
internal class StreamPump(
|
internal class StreamPump @JvmOverloads constructor(
|
||||||
val inputStream: InputStream,
|
val inputStream: InputStream,
|
||||||
val callback: (String) -> Unit = {}
|
val callback: (String) -> Unit = {}
|
||||||
) : Runnable {
|
) : Runnable {
|
||||||
|
@ -23,13 +23,6 @@ import java.io.IOException
|
|||||||
import java.util.zip.ZipOutputStream
|
import java.util.zip.ZipOutputStream
|
||||||
import java.util.zip.ZipInputStream
|
import java.util.zip.ZipInputStream
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Throws(IOException::class)
|
|
||||||
fun zip(src: String, destZip: String) {
|
|
||||||
zip(File(src), File(destZip), null)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 功能:把 src 目录下的所有文件进行 zip 格式的压缩,保存为指定 zip 文件
|
* 功能:把 src 目录下的所有文件进行 zip 格式的压缩,保存为指定 zip 文件
|
||||||
|
|
||||||
@ -43,8 +36,9 @@ fun zip(src: String, destZip: String) {
|
|||||||
* *
|
* *
|
||||||
* @throws java.io.IOException 压缩失败或无法读取
|
* @throws java.io.IOException 压缩失败或无法读取
|
||||||
*/
|
*/
|
||||||
|
@JvmOverloads
|
||||||
@Throws(IOException::class)
|
@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 ->
|
ZipOutputStream(destZip.outputStream()).use { zos ->
|
||||||
val basePath: String
|
val basePath: String
|
||||||
if (src.isDirectory)
|
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文件
|
* 将文件压缩成zip文件
|
||||||
|
|
||||||
@ -121,8 +110,9 @@ fun unzip(zip: File, dest: File) {
|
|||||||
* *
|
* *
|
||||||
* @throws java.io.IOException 解压失败或无法写入
|
* @throws java.io.IOException 解压失败或无法写入
|
||||||
*/
|
*/
|
||||||
|
@JvmOverloads
|
||||||
@Throws(IOException::class)
|
@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)
|
val buf = ByteArray(1024)
|
||||||
dest.mkdirs()
|
dest.mkdirs()
|
||||||
ZipInputStream(zip.inputStream()).use { zipFile ->
|
ZipInputStream(zip.inputStream()).use { zipFile ->
|
||||||
|
BIN
lib/JFoenix.jar
BIN
lib/JFoenix.jar
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user