FXML for decorator
This commit is contained in:
@@ -46,9 +46,7 @@ object Controllers {
|
|||||||
decorator.isCustomMaximize = false
|
decorator.isCustomMaximize = false
|
||||||
|
|
||||||
scene = Scene(decorator, 800.0, 480.0)
|
scene = Scene(decorator, 800.0, 480.0)
|
||||||
scene.stylesheets.addAll(Controllers::class.java.getResource("/css/jfoenix-design.css").toExternalForm(),
|
scene.stylesheets.addAll(*stylesheets)
|
||||||
Controllers::class.java.getResource("/assets/css/jfoenix-components.css").toExternalForm(),
|
|
||||||
Controllers::class.java.getResource("/assets/css/jfoenix-main-demo.css").toExternalForm())
|
|
||||||
stage.minWidth = 800.0
|
stage.minWidth = 800.0
|
||||||
stage.maxWidth = 800.0
|
stage.maxWidth = 800.0
|
||||||
stage.maxHeight = 480.0
|
stage.maxHeight = 480.0
|
||||||
@@ -56,7 +54,7 @@ object Controllers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun navigate(node: Node?) {
|
fun navigate(node: Node?) {
|
||||||
mainController.setContentPage(node)
|
//mainController.setContentPage(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> loadPane(s: String): T = FXMLLoader(Controllers::class.java.getResource("/assets/fxml/$s.fxml")).load()
|
private fun <T> loadPane(s: String): T = FXMLLoader(Controllers::class.java.getResource("/assets/fxml/$s.fxml")).load()
|
||||||
|
|||||||
@@ -25,14 +25,12 @@ import javafx.beans.property.BooleanProperty
|
|||||||
import javafx.beans.property.ObjectProperty
|
import javafx.beans.property.ObjectProperty
|
||||||
import javafx.beans.property.SimpleBooleanProperty
|
import javafx.beans.property.SimpleBooleanProperty
|
||||||
import javafx.beans.property.SimpleObjectProperty
|
import javafx.beans.property.SimpleObjectProperty
|
||||||
|
import javafx.fxml.FXML
|
||||||
import javafx.geometry.BoundingBox
|
import javafx.geometry.BoundingBox
|
||||||
import javafx.geometry.Bounds
|
import javafx.geometry.Bounds
|
||||||
import javafx.geometry.Insets
|
import javafx.geometry.Insets
|
||||||
import javafx.geometry.Pos
|
|
||||||
import javafx.scene.Cursor
|
import javafx.scene.Cursor
|
||||||
import javafx.scene.Node
|
import javafx.scene.Node
|
||||||
import javafx.scene.control.Button
|
|
||||||
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.*
|
||||||
@@ -41,9 +39,8 @@ 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 java.util.ArrayList
|
|
||||||
|
|
||||||
class Decorator @JvmOverloads constructor(private val primaryStage: Stage, node: Node, 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) : VBox() {
|
||||||
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,126 +50,58 @@ class Decorator @JvmOverloads constructor(private val primaryStage: Stage, node:
|
|||||||
private var allowMove: Boolean = false
|
private var allowMove: Boolean = false
|
||||||
private var isDragging: Boolean = false
|
private var isDragging: Boolean = false
|
||||||
private var windowDecoratorAnimation: Timeline? = null
|
private var windowDecoratorAnimation: Timeline? = null
|
||||||
private val contentPlaceHolder: StackPane
|
@FXML lateinit var contentPlaceHolder: StackPane
|
||||||
private val titleContainer: BorderPane
|
@FXML lateinit var titleContainer: BorderPane
|
||||||
|
@FXML lateinit var buttonsContainer: HBox
|
||||||
private val onCloseButtonAction: ObjectProperty<Runnable>
|
private val onCloseButtonAction: ObjectProperty<Runnable>
|
||||||
private val customMaximize: BooleanProperty
|
private val customMaximize: BooleanProperty
|
||||||
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
|
||||||
private val btnMax: JFXButton
|
@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
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
loadFXML("/assets/fxml/decorator.fxml")
|
||||||
|
|
||||||
this.xOffset = 0.0
|
this.xOffset = 0.0
|
||||||
this.yOffset = 0.0
|
this.yOffset = 0.0
|
||||||
this.allowMove = false
|
this.allowMove = false
|
||||||
this.isDragging = false
|
this.isDragging = false
|
||||||
this.contentPlaceHolder = StackPane()
|
|
||||||
this.onCloseButtonAction = SimpleObjectProperty(Runnable { this.primaryStage.close() })
|
this.onCloseButtonAction = SimpleObjectProperty(Runnable { this.primaryStage.close() })
|
||||||
this.customMaximize = SimpleBooleanProperty(false)
|
this.customMaximize = SimpleBooleanProperty(false)
|
||||||
this.maximized = false
|
this.maximized = false
|
||||||
this.primaryStage.initStyle(StageStyle.UNDECORATED)
|
this.primaryStage.initStyle(StageStyle.UNDECORATED)
|
||||||
this.isPickOnBounds = false
|
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)
|
||||||
this.styleClass.add("jfx-decorator")
|
|
||||||
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)
|
|
||||||
minus.setSize(12.0, 2.0)
|
minus.setSize(12.0, 2.0)
|
||||||
minus.translateY = 4.0
|
minus.translateY = 4.0
|
||||||
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)
|
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)
|
resizeMax.setSize(12.0, 12.0)
|
||||||
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)
|
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)
|
resizeMin.setSize(12.0, 12.0)
|
||||||
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)
|
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)
|
close.setSize(12.0, 12.0)
|
||||||
val btnClose = JFXButton()
|
|
||||||
btnClose.styleClass.add("jfx-decorator-button")
|
|
||||||
btnClose.cursor = Cursor.HAND
|
|
||||||
btnClose.setOnAction { action -> (this.onCloseButtonAction.get() as Runnable).run() }
|
|
||||||
btnClose.graphic = close
|
btnClose.graphic = close
|
||||||
btnClose.ripplerFill = Color.WHITE
|
|
||||||
val btnMin = JFXButton()
|
|
||||||
btnMin.styleClass.add("jfx-decorator-button")
|
|
||||||
btnMin.cursor = Cursor.HAND
|
|
||||||
btnMin.setOnAction { action -> this.primaryStage.isIconified = true }
|
|
||||||
btnMin.graphic = minus
|
btnMin.graphic = minus
|
||||||
btnMin.ripplerFill = Color.WHITE
|
|
||||||
this.btnMax = JFXButton()
|
|
||||||
this.btnMax.styleClass.add("jfx-decorator-button")
|
|
||||||
this.btnMax.cursor = Cursor.HAND
|
|
||||||
this.btnMax.ripplerFill = Color.WHITE
|
|
||||||
this.btnMax.setOnAction { action ->
|
|
||||||
if (!this.isCustomMaximize) {
|
|
||||||
this.primaryStage.isMaximized = !this.primaryStage.isMaximized
|
|
||||||
this.maximized = this.primaryStage.isMaximized
|
|
||||||
if (this.primaryStage.isMaximized) {
|
|
||||||
this.btnMax.graphic = resizeMin
|
|
||||||
this.btnMax.tooltip = Tooltip("Restore Down")
|
|
||||||
} else {
|
|
||||||
this.btnMax.graphic = resizeMax
|
|
||||||
this.btnMax.tooltip = Tooltip("Maximize")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!this.maximized) {
|
|
||||||
this.originalBox = BoundingBox(primaryStage.x, primaryStage.y, primaryStage.width, primaryStage.height)
|
|
||||||
val screen = Screen.getScreensForRectangle(primaryStage.x, primaryStage.y, primaryStage.width, primaryStage.height)[0] as Screen
|
|
||||||
val bounds = screen.visualBounds
|
|
||||||
this.maximizedBox = BoundingBox(bounds.minX, bounds.minY, bounds.width, bounds.height)
|
|
||||||
primaryStage.x = this.maximizedBox!!.minX
|
|
||||||
primaryStage.y = this.maximizedBox!!.minY
|
|
||||||
primaryStage.width = this.maximizedBox!!.width
|
|
||||||
primaryStage.height = this.maximizedBox!!.height
|
|
||||||
this.btnMax.graphic = resizeMin
|
|
||||||
this.btnMax.tooltip = Tooltip("Restore Down")
|
|
||||||
} else {
|
|
||||||
primaryStage.x = this.originalBox!!.minX
|
|
||||||
primaryStage.y = this.originalBox!!.minY
|
|
||||||
primaryStage.width = this.originalBox!!.width
|
|
||||||
primaryStage.height = this.originalBox!!.height
|
|
||||||
this.originalBox = null
|
|
||||||
this.btnMax.graphic = resizeMax
|
|
||||||
this.btnMax.tooltip = Tooltip("Maximize")
|
|
||||||
}
|
|
||||||
|
|
||||||
this.maximized = !this.maximized
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
this.btnMax.graphic = resizeMax
|
this.btnMax.graphic = resizeMax
|
||||||
titleContainer = BorderPane()
|
|
||||||
titleContainer.styleClass += "jfx-decorator-buttons-container"
|
|
||||||
titleContainer.isPickOnBounds = false
|
|
||||||
val titleWrapper = HBox()
|
|
||||||
titleWrapper.style += "-fx-padding: 15;"
|
|
||||||
titleWrapper.alignment = Pos.CENTER_LEFT
|
|
||||||
val title = Label("Hello Minecraft! Launcher")
|
|
||||||
title.alignment = Pos.CENTER_LEFT
|
|
||||||
title.style += "--fx-background-color: transparent; -fx-text-fill: white; -fx-font-size: 15px;"
|
|
||||||
title.isMouseTransparent = false
|
|
||||||
titleWrapper.children.setAll(title)
|
|
||||||
titleContainer.left = titleWrapper
|
|
||||||
|
|
||||||
val buttonsContainer = HBox()
|
|
||||||
buttonsContainer.styleClass.add("jfx-decorator-buttons-container")
|
|
||||||
buttonsContainer.background = Background(*arrayOf(BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY)))
|
buttonsContainer.background = Background(*arrayOf(BackgroundFill(Color.BLACK, CornerRadii.EMPTY, Insets.EMPTY)))
|
||||||
buttonsContainer.padding = Insets(4.0)
|
|
||||||
buttonsContainer.alignment = Pos.CENTER_RIGHT
|
|
||||||
titleContainer.addEventHandler(MouseEvent.MOUSE_CLICKED) { mouseEvent ->
|
titleContainer.addEventHandler(MouseEvent.MOUSE_CLICKED) { mouseEvent ->
|
||||||
if (mouseEvent.clickCount == 2) {
|
if (mouseEvent.clickCount == 2) {
|
||||||
this.btnMax.fire()
|
this.btnMax.fire()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
val btns = ArrayList<Button>()
|
|
||||||
|
|
||||||
if (min) {
|
if (!min) buttonsContainer.children.remove(btnMin)
|
||||||
btns.add(btnMin)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (max) {
|
if (!max) buttonsContainer.children.remove(btnMax)
|
||||||
btns.add(this.btnMax)
|
|
||||||
}
|
|
||||||
|
|
||||||
btns.add(btnClose)
|
|
||||||
buttonsContainer.children.addAll(btns)
|
|
||||||
titleContainer.addEventHandler(MouseEvent.MOUSE_ENTERED) { enter -> this.allowMove = true }
|
titleContainer.addEventHandler(MouseEvent.MOUSE_ENTERED) { enter -> this.allowMove = true }
|
||||||
titleContainer.addEventHandler(MouseEvent.MOUSE_EXITED) { enter ->
|
titleContainer.addEventHandler(MouseEvent.MOUSE_EXITED) { enter ->
|
||||||
if (!this.isDragging) {
|
if (!this.isDragging) {
|
||||||
@@ -180,130 +109,174 @@ class Decorator @JvmOverloads constructor(private val primaryStage: Stage, node:
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
buttonsContainer.minWidth = 180.0
|
|
||||||
|
|
||||||
titleContainer.right = buttonsContainer
|
|
||||||
this.contentPlaceHolder.styleClass.add("jfx-decorator-content-container")
|
|
||||||
this.contentPlaceHolder.setMinSize(0.0, 0.0)
|
|
||||||
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)
|
||||||
VBox.setVgrow(this.contentPlaceHolder, Priority.ALWAYS)
|
|
||||||
this.contentPlaceHolder.styleClass.add("resize-border")
|
|
||||||
this.contentPlaceHolder.border = Border(BorderStroke(Color.BLACK, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, BorderWidths(0.0, 4.0, 4.0, 4.0)))
|
this.contentPlaceHolder.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())
|
||||||
node.setClip(clip)
|
node.setClip(clip)
|
||||||
this.children.addAll(titleContainer, this.contentPlaceHolder)
|
}
|
||||||
this.setOnMouseMoved { mouseEvent ->
|
|
||||||
if (!this.primaryStage.isMaximized && !this.primaryStage.isFullScreen && !this.maximized) {
|
|
||||||
if (!this.primaryStage.isResizable) {
|
|
||||||
this.updateInitMouseValues(mouseEvent)
|
|
||||||
} else {
|
|
||||||
val x = mouseEvent.x
|
|
||||||
val y = mouseEvent.y
|
|
||||||
val boundsInParent = this.boundsInParent
|
|
||||||
if (this.contentPlaceHolder.border != null && this.contentPlaceHolder.border.strokes.size > 0) {
|
|
||||||
val borderWidth = this.contentPlaceHolder.snappedLeftInset()
|
|
||||||
if (this.isRightEdge(x, y, boundsInParent)) {
|
|
||||||
if (y < borderWidth) {
|
|
||||||
this.cursor = Cursor.NE_RESIZE
|
|
||||||
} else if (y > this.height - borderWidth) {
|
|
||||||
this.cursor = Cursor.SE_RESIZE
|
|
||||||
} else {
|
|
||||||
this.cursor = Cursor.E_RESIZE
|
|
||||||
}
|
|
||||||
} else if (this.isLeftEdge(x, y, boundsInParent)) {
|
|
||||||
if (y < borderWidth) {
|
|
||||||
this.cursor = Cursor.NW_RESIZE
|
|
||||||
} else if (y > this.height - borderWidth) {
|
|
||||||
this.cursor = Cursor.SW_RESIZE
|
|
||||||
} else {
|
|
||||||
this.cursor = Cursor.W_RESIZE
|
|
||||||
}
|
|
||||||
} else if (this.isTopEdge(x, y, boundsInParent)) {
|
|
||||||
this.cursor = Cursor.N_RESIZE
|
|
||||||
} else if (this.isBottomEdge(x, y, boundsInParent)) {
|
|
||||||
this.cursor = Cursor.S_RESIZE
|
|
||||||
} else {
|
|
||||||
this.cursor = Cursor.DEFAULT
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updateInitMouseValues(mouseEvent)
|
fun onMouseMoved(mouseEvent: MouseEvent) {
|
||||||
}
|
if (!this.primaryStage.isMaximized && !this.primaryStage.isFullScreen && !this.maximized) {
|
||||||
|
if (!this.primaryStage.isResizable) {
|
||||||
}
|
this.updateInitMouseValues(mouseEvent)
|
||||||
} else {
|
} else {
|
||||||
this.cursor = Cursor.DEFAULT
|
val x = mouseEvent.x
|
||||||
}
|
val y = mouseEvent.y
|
||||||
}
|
val boundsInParent = this.boundsInParent
|
||||||
this.setOnMouseReleased { mouseEvent -> this.isDragging = false }
|
if (this.contentPlaceHolder.border != null && this.contentPlaceHolder.border.strokes.size > 0) {
|
||||||
this.setOnMouseDragged { mouseEvent ->
|
val borderWidth = this.contentPlaceHolder.snappedLeftInset()
|
||||||
this.isDragging = true
|
if (this.isRightEdge(x, y, boundsInParent)) {
|
||||||
if (mouseEvent.isPrimaryButtonDown && (this.xOffset != -1.0 || this.yOffset != -1.0)) {
|
if (y < borderWidth) {
|
||||||
if (!this.primaryStage.isFullScreen && !mouseEvent.isStillSincePress && !this.primaryStage.isMaximized && !this.maximized) {
|
this.cursor = Cursor.NE_RESIZE
|
||||||
this.newX = mouseEvent.screenX
|
} else if (y > this.height - borderWidth) {
|
||||||
this.newY = mouseEvent.screenY
|
this.cursor = Cursor.SE_RESIZE
|
||||||
val deltax = this.newX - this.initX
|
} else {
|
||||||
val deltay = this.newY - this.initY
|
this.cursor = Cursor.E_RESIZE
|
||||||
val cursor = this.cursor
|
|
||||||
if (Cursor.E_RESIZE == cursor) {
|
|
||||||
this.setStageWidth(this.primaryStage.width + deltax)
|
|
||||||
mouseEvent.consume()
|
|
||||||
} else if (Cursor.NE_RESIZE == cursor) {
|
|
||||||
if (this.setStageHeight(this.primaryStage.height - deltay)) {
|
|
||||||
this.primaryStage.y = this.primaryStage.y + deltay
|
|
||||||
}
|
}
|
||||||
|
} else if (this.isLeftEdge(x, y, boundsInParent)) {
|
||||||
this.setStageWidth(this.primaryStage.width + deltax)
|
if (y < borderWidth) {
|
||||||
mouseEvent.consume()
|
this.cursor = Cursor.NW_RESIZE
|
||||||
} else if (Cursor.SE_RESIZE == cursor) {
|
} else if (y > this.height - borderWidth) {
|
||||||
this.setStageWidth(this.primaryStage.width + deltax)
|
this.cursor = Cursor.SW_RESIZE
|
||||||
this.setStageHeight(this.primaryStage.height + deltay)
|
} else {
|
||||||
mouseEvent.consume()
|
this.cursor = Cursor.W_RESIZE
|
||||||
} else if (Cursor.S_RESIZE == cursor) {
|
|
||||||
this.setStageHeight(this.primaryStage.height + deltay)
|
|
||||||
mouseEvent.consume()
|
|
||||||
} else if (Cursor.W_RESIZE == cursor) {
|
|
||||||
if (this.setStageWidth(this.primaryStage.width - deltax)) {
|
|
||||||
this.primaryStage.x = this.primaryStage.x + deltax
|
|
||||||
}
|
}
|
||||||
|
} else if (this.isTopEdge(x, y, boundsInParent)) {
|
||||||
mouseEvent.consume()
|
this.cursor = Cursor.N_RESIZE
|
||||||
} else if (Cursor.SW_RESIZE == cursor) {
|
} else if (this.isBottomEdge(x, y, boundsInParent)) {
|
||||||
if (this.setStageWidth(this.primaryStage.width - deltax)) {
|
this.cursor = Cursor.S_RESIZE
|
||||||
this.primaryStage.x = this.primaryStage.x + deltax
|
} else {
|
||||||
}
|
this.cursor = Cursor.DEFAULT
|
||||||
|
|
||||||
this.setStageHeight(this.primaryStage.height + deltay)
|
|
||||||
mouseEvent.consume()
|
|
||||||
} else if (Cursor.NW_RESIZE == cursor) {
|
|
||||||
if (this.setStageWidth(this.primaryStage.width - deltax)) {
|
|
||||||
this.primaryStage.x = this.primaryStage.x + deltax
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.setStageHeight(this.primaryStage.height - deltay)) {
|
|
||||||
this.primaryStage.y = this.primaryStage.y + deltay
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseEvent.consume()
|
|
||||||
} else if (Cursor.N_RESIZE == cursor) {
|
|
||||||
if (this.setStageHeight(this.primaryStage.height - deltay)) {
|
|
||||||
this.primaryStage.y = this.primaryStage.y + deltay
|
|
||||||
}
|
|
||||||
|
|
||||||
mouseEvent.consume()
|
|
||||||
} else if (this.allowMove) {
|
|
||||||
this.primaryStage.x = mouseEvent.screenX - this.xOffset
|
|
||||||
this.primaryStage.y = mouseEvent.screenY - this.yOffset
|
|
||||||
mouseEvent.consume()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.updateInitMouseValues(mouseEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.cursor = Cursor.DEFAULT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onMouseReleased() {
|
||||||
|
this.isDragging = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onMouseDragged(mouseEvent: MouseEvent) {
|
||||||
|
this.isDragging = true
|
||||||
|
if (mouseEvent.isPrimaryButtonDown && (this.xOffset != -1.0 || this.yOffset != -1.0)) {
|
||||||
|
if (!this.primaryStage.isFullScreen && !mouseEvent.isStillSincePress && !this.primaryStage.isMaximized && !this.maximized) {
|
||||||
|
this.newX = mouseEvent.screenX
|
||||||
|
this.newY = mouseEvent.screenY
|
||||||
|
val deltax = this.newX - this.initX
|
||||||
|
val deltay = this.newY - this.initY
|
||||||
|
val cursor = this.cursor
|
||||||
|
if (Cursor.E_RESIZE == cursor) {
|
||||||
|
this.setStageWidth(this.primaryStage.width + deltax)
|
||||||
|
mouseEvent.consume()
|
||||||
|
} else if (Cursor.NE_RESIZE == cursor) {
|
||||||
|
if (this.setStageHeight(this.primaryStage.height - deltay)) {
|
||||||
|
this.primaryStage.y = this.primaryStage.y + deltay
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setStageWidth(this.primaryStage.width + deltax)
|
||||||
|
mouseEvent.consume()
|
||||||
|
} else if (Cursor.SE_RESIZE == cursor) {
|
||||||
|
this.setStageWidth(this.primaryStage.width + deltax)
|
||||||
|
this.setStageHeight(this.primaryStage.height + deltay)
|
||||||
|
mouseEvent.consume()
|
||||||
|
} else if (Cursor.S_RESIZE == cursor) {
|
||||||
|
this.setStageHeight(this.primaryStage.height + deltay)
|
||||||
|
mouseEvent.consume()
|
||||||
|
} else if (Cursor.W_RESIZE == cursor) {
|
||||||
|
if (this.setStageWidth(this.primaryStage.width - deltax)) {
|
||||||
|
this.primaryStage.x = this.primaryStage.x + deltax
|
||||||
|
}
|
||||||
|
|
||||||
|
mouseEvent.consume()
|
||||||
|
} else if (Cursor.SW_RESIZE == cursor) {
|
||||||
|
if (this.setStageWidth(this.primaryStage.width - deltax)) {
|
||||||
|
this.primaryStage.x = this.primaryStage.x + deltax
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setStageHeight(this.primaryStage.height + deltay)
|
||||||
|
mouseEvent.consume()
|
||||||
|
} else if (Cursor.NW_RESIZE == cursor) {
|
||||||
|
if (this.setStageWidth(this.primaryStage.width - deltax)) {
|
||||||
|
this.primaryStage.x = this.primaryStage.x + deltax
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.setStageHeight(this.primaryStage.height - deltay)) {
|
||||||
|
this.primaryStage.y = this.primaryStage.y + deltay
|
||||||
|
}
|
||||||
|
|
||||||
|
mouseEvent.consume()
|
||||||
|
} else if (Cursor.N_RESIZE == cursor) {
|
||||||
|
if (this.setStageHeight(this.primaryStage.height - deltay)) {
|
||||||
|
this.primaryStage.y = this.primaryStage.y + deltay
|
||||||
|
}
|
||||||
|
|
||||||
|
mouseEvent.consume()
|
||||||
|
} else if (this.allowMove) {
|
||||||
|
this.primaryStage.x = mouseEvent.screenX - this.xOffset
|
||||||
|
this.primaryStage.y = mouseEvent.screenY - this.yOffset
|
||||||
|
mouseEvent.consume()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onMin() {
|
||||||
|
this.primaryStage.isIconified = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onMax() {
|
||||||
|
if (!max) return
|
||||||
|
if (!this.isCustomMaximize) {
|
||||||
|
this.primaryStage.isMaximized = !this.primaryStage.isMaximized
|
||||||
|
this.maximized = this.primaryStage.isMaximized
|
||||||
|
if (this.primaryStage.isMaximized) {
|
||||||
|
this.btnMax.graphic = resizeMin
|
||||||
|
this.btnMax.tooltip = Tooltip("Restore Down")
|
||||||
|
} else {
|
||||||
|
this.btnMax.graphic = resizeMax
|
||||||
|
this.btnMax.tooltip = Tooltip("Maximize")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!this.maximized) {
|
||||||
|
this.originalBox = BoundingBox(primaryStage.x, primaryStage.y, primaryStage.width, primaryStage.height)
|
||||||
|
val screen = Screen.getScreensForRectangle(primaryStage.x, primaryStage.y, primaryStage.width, primaryStage.height)[0] as Screen
|
||||||
|
val bounds = screen.visualBounds
|
||||||
|
this.maximizedBox = BoundingBox(bounds.minX, bounds.minY, bounds.width, bounds.height)
|
||||||
|
primaryStage.x = this.maximizedBox!!.minX
|
||||||
|
primaryStage.y = this.maximizedBox!!.minY
|
||||||
|
primaryStage.width = this.maximizedBox!!.width
|
||||||
|
primaryStage.height = this.maximizedBox!!.height
|
||||||
|
this.btnMax.graphic = resizeMin
|
||||||
|
this.btnMax.tooltip = Tooltip("Restore Down")
|
||||||
|
} else {
|
||||||
|
primaryStage.x = this.originalBox!!.minX
|
||||||
|
primaryStage.y = this.originalBox!!.minY
|
||||||
|
primaryStage.width = this.originalBox!!.width
|
||||||
|
primaryStage.height = this.originalBox!!.height
|
||||||
|
this.originalBox = null
|
||||||
|
this.btnMax.graphic = resizeMax
|
||||||
|
this.btnMax.tooltip = Tooltip("Maximize")
|
||||||
|
}
|
||||||
|
|
||||||
|
this.maximized = !this.maximized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onClose() {
|
||||||
|
(this.onCloseButtonAction.get() as Runnable).run()
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateInitMouseValues(mouseEvent: MouseEvent) {
|
private fun updateInitMouseValues(mouseEvent: MouseEvent) {
|
||||||
this.initX = mouseEvent.screenX
|
this.initX = mouseEvent.screenX
|
||||||
this.initY = mouseEvent.screenY
|
this.initY = mouseEvent.screenY
|
||||||
@@ -371,7 +344,6 @@ class Decorator @JvmOverloads constructor(private val primaryStage: Stage, node:
|
|||||||
if (this.maximized != maximized) {
|
if (this.maximized != maximized) {
|
||||||
Platform.runLater { this.btnMax.fire() }
|
Platform.runLater { this.btnMax.fire() }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setContent(content: Node) {
|
fun setContent(content: Node) {
|
||||||
|
|||||||
@@ -25,10 +25,15 @@ import javafx.event.ActionEvent
|
|||||||
import javafx.event.EventHandler
|
import javafx.event.EventHandler
|
||||||
import javafx.fxml.FXMLLoader
|
import javafx.fxml.FXMLLoader
|
||||||
import javafx.scene.Node
|
import javafx.scene.Node
|
||||||
|
import javafx.scene.Parent
|
||||||
|
import javafx.scene.Scene
|
||||||
import javafx.scene.control.ListView
|
import javafx.scene.control.ListView
|
||||||
import javafx.scene.control.ScrollBar
|
import javafx.scene.control.ScrollBar
|
||||||
|
import javafx.scene.image.WritableImage
|
||||||
import javafx.scene.input.MouseEvent
|
import javafx.scene.input.MouseEvent
|
||||||
import javafx.scene.input.ScrollEvent
|
import javafx.scene.input.ScrollEvent
|
||||||
|
import javafx.scene.layout.Pane
|
||||||
|
import javafx.scene.shape.Rectangle
|
||||||
import javafx.util.Duration
|
import javafx.util.Duration
|
||||||
|
|
||||||
fun Node.loadFXML(absolutePath: String) {
|
fun Node.loadFXML(absolutePath: String) {
|
||||||
@@ -87,3 +92,20 @@ fun ListView<*>.smoothScrolling() {
|
|||||||
fun runOnUiThread(runnable: () -> Unit) = {
|
fun runOnUiThread(runnable: () -> Unit) = {
|
||||||
JFXUtilities.runInFX(runnable)
|
JFXUtilities.runInFX(runnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun takeSnapshot(node: Parent, width: Double, height: Double): WritableImage {
|
||||||
|
val scene = Scene(node, width, height)
|
||||||
|
scene.stylesheets.addAll(*stylesheets)
|
||||||
|
return scene.snapshot(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOverflowHidden(node: Pane) {
|
||||||
|
val rectangle = Rectangle()
|
||||||
|
rectangle.widthProperty().bind(node.widthProperty())
|
||||||
|
rectangle.heightProperty().bind(node.heightProperty())
|
||||||
|
node.clip = rectangle
|
||||||
|
}
|
||||||
|
|
||||||
|
val stylesheets = arrayOf(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())
|
||||||
@@ -43,87 +43,4 @@ import org.jackhuang.hmcl.ui.wizard.Wizard
|
|||||||
*/
|
*/
|
||||||
class MainController {
|
class MainController {
|
||||||
|
|
||||||
/**
|
|
||||||
* A combo box that allows user to select Minecraft directory.
|
|
||||||
*/
|
|
||||||
@FXML lateinit var comboProfiles: JFXComboBox<String> // TODO: JFXComboBox<Profile>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The button that is to launch the selected game version.
|
|
||||||
*/
|
|
||||||
@FXML lateinit var buttonLaunch: JFXButton
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A central pane that contains popups like (global) version settings, app settings, game installations and so on.
|
|
||||||
*/
|
|
||||||
@FXML lateinit var page: StackPane
|
|
||||||
|
|
||||||
@FXML lateinit var listVersions: JFXListView<VersionListItem> // TODO: JFXListView<Version> including icon, title, game version(if equals to title, hidden)
|
|
||||||
|
|
||||||
lateinit var animationHandler: TransitionHandler
|
|
||||||
|
|
||||||
// TODO: implementing functions.
|
|
||||||
fun initialize() {
|
|
||||||
Controllers.mainController = this
|
|
||||||
|
|
||||||
animationHandler = TransitionHandler(page)
|
|
||||||
|
|
||||||
EVENT_BUS.channel<RefreshedVersionsEvent>() += this::loadVersions
|
|
||||||
EVENT_BUS.channel<ProfileLoadingEvent>() += this::onProfilesLoading
|
|
||||||
EVENT_BUS.channel<ProfileChangedEvent>() += this::onProfileChanged
|
|
||||||
|
|
||||||
listVersions.setOnMouseClicked {
|
|
||||||
if (it.clickCount == 2) {
|
|
||||||
setContentPage(Controllers.versionPane)
|
|
||||||
val id = listVersions.selectionModel.selectedItem.id
|
|
||||||
|
|
||||||
Controllers.versionController.loadVersionSetting(id, Settings.getLastProfile().getVersionSetting(id))
|
|
||||||
} else
|
|
||||||
it.consume()
|
|
||||||
}
|
|
||||||
|
|
||||||
listVersions.smoothScrolling()
|
|
||||||
|
|
||||||
Settings.onProfileLoading()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val empty = Pane()
|
|
||||||
|
|
||||||
fun setContentPage(node: Node?) {
|
|
||||||
animationHandler.setContent(node ?: empty, ContainerAnimations.FADE.animationProducer)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun installNewVersion() {
|
|
||||||
setContentPage(Wizard.createWizard("Install New Game", DownloadWizardProvider()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onProfilesLoading() {
|
|
||||||
// TODO: Profiles
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onProfileChanged(event: ProfileChangedEvent) {
|
|
||||||
val profile = event.value
|
|
||||||
profile.selectedVersionProperty.addListener { _, _, newValue ->
|
|
||||||
versionChanged(newValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val versionListItems = mutableMapOf<String, VersionListItem>()
|
|
||||||
|
|
||||||
fun loadVersions() {
|
|
||||||
val profile = Settings.getLastProfile()
|
|
||||||
val list = mutableListOf<VersionListItem>()
|
|
||||||
versionListItems.clear()
|
|
||||||
profile.repository.getVersions().forEach {
|
|
||||||
val item = VersionListItem(it.id, minecraftVersion(Settings.getLastProfile().repository.getVersionJar(it.id)) ?: "Unknown")
|
|
||||||
list += item
|
|
||||||
versionListItems += it.id to item
|
|
||||||
}
|
|
||||||
|
|
||||||
listVersions.items = FXCollections.observableList(list)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun versionChanged(selectedVersion: String) {
|
|
||||||
listVersions.selectionModel.select(versionListItems[selectedVersion])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -21,12 +21,17 @@ import javafx.animation.KeyFrame
|
|||||||
import javafx.animation.Timeline
|
import javafx.animation.Timeline
|
||||||
import javafx.event.EventHandler
|
import javafx.event.EventHandler
|
||||||
import javafx.scene.Node
|
import javafx.scene.Node
|
||||||
|
import javafx.scene.Parent
|
||||||
import javafx.scene.SnapshotParameters
|
import javafx.scene.SnapshotParameters
|
||||||
import javafx.scene.image.ImageView
|
import javafx.scene.image.ImageView
|
||||||
import javafx.scene.image.WritableImage
|
import javafx.scene.image.WritableImage
|
||||||
import javafx.scene.layout.StackPane
|
import javafx.scene.layout.StackPane
|
||||||
import javafx.util.Duration
|
import javafx.util.Duration
|
||||||
|
import org.jackhuang.hmcl.ui.takeSnapshot
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param view A stack pane that contains another control that is [Parent]
|
||||||
|
*/
|
||||||
class TransitionHandler(override val view: StackPane): AnimationHandler {
|
class TransitionHandler(override val view: StackPane): AnimationHandler {
|
||||||
private var animation: Timeline? = null
|
private var animation: Timeline? = null
|
||||||
|
|
||||||
@@ -62,13 +67,16 @@ class TransitionHandler(override val view: StackPane): AnimationHandler {
|
|||||||
|
|
||||||
private fun updateContent(newView: Node) {
|
private fun updateContent(newView: Node) {
|
||||||
if (view.width > 0 && view.height > 0) {
|
if (view.width > 0 && view.height > 0) {
|
||||||
val image = view.snapshot(SnapshotParameters(), null)
|
val content = view.children.firstOrNull()
|
||||||
val x = (image.width - view.width) / 2
|
val image: WritableImage
|
||||||
val y = image.height - view.height
|
if (content != null && content is Parent) {
|
||||||
val newImage = WritableImage(image.pixelReader, x.toInt(), y.toInt(), view.width.toInt(), view.height.toInt())
|
view.children.setAll()
|
||||||
snapshot.image = newImage
|
image = takeSnapshot(content, view.width, view.height)
|
||||||
snapshot.fitWidth = newImage.width
|
view.children.setAll(content)
|
||||||
snapshot.fitHeight = newImage.height
|
} else image = view.snapshot(SnapshotParameters(), WritableImage(view.width.toInt(), view.height.toInt()))
|
||||||
|
snapshot.image = image
|
||||||
|
snapshot.fitWidth = view.width
|
||||||
|
snapshot.fitHeight = view.height
|
||||||
} else
|
} else
|
||||||
snapshot.image = null
|
snapshot.image = null
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ class InstallTypePage(private val controller: WizardController): StackPane(), Wi
|
|||||||
init {
|
init {
|
||||||
loadFXML("/assets/fxml/download/dltype.fxml")
|
loadFXML("/assets/fxml/download/dltype.fxml")
|
||||||
|
|
||||||
list.selectionModel.selectedIndexProperty().addListener { _, _, newValue ->
|
list.setOnMouseClicked {
|
||||||
controller.settings[INSTALL_TYPE] = newValue
|
controller.settings[INSTALL_TYPE] = list.selectionModel.selectedIndex
|
||||||
controller.onNext()
|
controller.onNext()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.jfoenix.concurrency.JFXUtilities
|
|||||||
import com.jfoenix.controls.JFXButton
|
import com.jfoenix.controls.JFXButton
|
||||||
import com.jfoenix.controls.JFXProgressBar
|
import com.jfoenix.controls.JFXProgressBar
|
||||||
import com.jfoenix.controls.JFXToolbar
|
import com.jfoenix.controls.JFXToolbar
|
||||||
|
import com.jfoenix.effects.JFXDepthManager
|
||||||
import javafx.fxml.FXML
|
import javafx.fxml.FXML
|
||||||
import javafx.scene.Node
|
import javafx.scene.Node
|
||||||
import javafx.scene.control.Label
|
import javafx.scene.control.Label
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
.jfx-decorator .resize-border {
|
.jfx-decorator .resize-border {
|
||||||
-fx-border-color: -fx-decorator-color;
|
-fx-border-color: -fx-decorator-color;
|
||||||
-fx-border-width: 0 4 4 4;
|
-fx-border-width: 0 1 1 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.jfx-text-area, .text-area {
|
.jfx-text-area, .text-area {
|
||||||
|
|||||||
56
HMCL/src/main/resources/assets/fxml/decorator.fxml
Normal file
56
HMCL/src/main/resources/assets/fxml/decorator.fxml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.control.*?>
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
|
<?import com.jfoenix.controls.JFXButton?>
|
||||||
|
<?import javafx.scene.Cursor?>
|
||||||
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import java.lang.String?>
|
||||||
|
<fx:root xmlns="http://javafx.com/javafx"
|
||||||
|
type="VBox"
|
||||||
|
xmlns:fx="http://javafx.com/fxml"
|
||||||
|
styleClass="jfx-decorator"
|
||||||
|
pickOnBounds="false"
|
||||||
|
onMouseReleased="#onMouseReleased"
|
||||||
|
onMouseDragged="#onMouseDragged"
|
||||||
|
onMouseMoved="#onMouseMoved">
|
||||||
|
|
||||||
|
<BorderPane fx:id="titleContainer" styleClass="jfx-decorator-buttons-container" pickOnBounds="false">
|
||||||
|
<left>
|
||||||
|
<HBox fx:id="titleWrapper" alignment="CENTER_LEFT" style="-fx-padding: 15;">
|
||||||
|
<Label text="Hello Minecraft! Launcher" mouseTransparent="false" style="-fx-background-color: transparent; -fx-text-fill: white; -fx-font-size: 15px;" />
|
||||||
|
</HBox>
|
||||||
|
</left>
|
||||||
|
<right>
|
||||||
|
<HBox fx:id="buttonsContainer" styleClass="jfx-decorator-buttons-container" alignment="CENTER_RIGHT" minWidth="180">
|
||||||
|
<padding>
|
||||||
|
<Insets topRightBottomLeft="4.0" />
|
||||||
|
</padding>
|
||||||
|
<JFXButton fx:id="btnMin" styleClass="jfx-decorator-button" ripplerFill="white" onAction="#onMin">
|
||||||
|
<cursor>
|
||||||
|
<Cursor fx:constant="HAND" />
|
||||||
|
</cursor>
|
||||||
|
</JFXButton>
|
||||||
|
<JFXButton fx:id="btnMax" styleClass="jfx-decorator-button" ripplerFill="white" onAction="#onMax">
|
||||||
|
<cursor>
|
||||||
|
<Cursor fx:constant="HAND" />
|
||||||
|
</cursor>
|
||||||
|
</JFXButton>
|
||||||
|
<JFXButton fx:id="btnClose" styleClass="jfx-decorator-button" ripplerFill="white" onAction="#onClose">
|
||||||
|
<cursor>
|
||||||
|
<Cursor fx:constant="HAND" />
|
||||||
|
</cursor>
|
||||||
|
</JFXButton>
|
||||||
|
</HBox>
|
||||||
|
</right>
|
||||||
|
</BorderPane>
|
||||||
|
|
||||||
|
<StackPane fx:id="contentPlaceHolder" styleClass="jfx-decorator-content-container resize-border" minWidth="0" minHeight="0" VBox.vgrow="ALWAYS">
|
||||||
|
<styleClass>
|
||||||
|
<String fx:value="jfx-decorator-content-container" />
|
||||||
|
<String fx:value="resize-border" />
|
||||||
|
</styleClass>
|
||||||
|
<!-- Node -->
|
||||||
|
</StackPane>
|
||||||
|
</fx:root>
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
<?import javafx.scene.control.*?>
|
<?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"
|
||||||
@@ -20,7 +21,7 @@
|
|||||||
<StackPane>
|
<StackPane>
|
||||||
<JFXListView fx:id="listVersions" styleClass="mylistview" style="-fx-background-color: #F1F1F1;" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
|
<JFXListView fx:id="listVersions" styleClass="mylistview" style="-fx-background-color: #F1F1F1;" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
|
||||||
<AnchorPane pickOnBounds="false">
|
<AnchorPane pickOnBounds="false">
|
||||||
<JFXButton onMouseClicked="#installNewVersion" 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;">
|
<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>
|
<graphic>
|
||||||
<fx:include source="/assets/svg/plus.fxml" />
|
<fx:include source="/assets/svg/plus.fxml" />
|
||||||
</graphic>
|
</graphic>
|
||||||
@@ -30,6 +31,41 @@
|
|||||||
</center>
|
</center>
|
||||||
</BorderPane>
|
</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>
|
||||||
|
|||||||
@@ -8,31 +8,11 @@
|
|||||||
<StackPane xmlns="http://javafx.com/javafx"
|
<StackPane xmlns="http://javafx.com/javafx"
|
||||||
xmlns:fx="http://javafx.com/fxml"
|
xmlns:fx="http://javafx.com/fxml"
|
||||||
fx:controller="org.jackhuang.hmcl.ui.VersionController">
|
fx:controller="org.jackhuang.hmcl.ui.VersionController">
|
||||||
<VBox spacing="20" GridPane.rowIndex="0">
|
<BorderPane>
|
||||||
<JFXToolbar maxHeight="20" styleClass="jfx-tool-bar">
|
<center>
|
||||||
<leftItems>
|
|
||||||
<JFXButton fx:id="backButton" maxHeight="20" styleClass="toggle-icon3"
|
|
||||||
StackPane.alignment="CENTER_LEFT">
|
|
||||||
<graphic>
|
|
||||||
<fx:include source="/assets/svg/arrow-left.fxml" />
|
|
||||||
</graphic>
|
|
||||||
<StackPane.margin>
|
|
||||||
<Insets left="20" />
|
|
||||||
</StackPane.margin>
|
|
||||||
</JFXButton>
|
|
||||||
<Label fx:id="titleLabel" style="-fx-text-fill:WHITE; -fx-font-size: 20;"
|
|
||||||
StackPane.alignment="CENTER_LEFT"/>
|
|
||||||
</leftItems>
|
|
||||||
<rightItems>
|
|
||||||
|
|
||||||
</rightItems>
|
|
||||||
</JFXToolbar>
|
|
||||||
<ScrollPane fx:id="scroll"
|
<ScrollPane fx:id="scroll"
|
||||||
style="-fx-margin: 10; -fx-background-color: white; -fx-font-size: 14; -fx-pref-width: 100%; "
|
style="-fx-background-color: white; -fx-font-size: 14; -fx-pref-width: 100%; "
|
||||||
fitToHeight="true" fitToWidth="true">
|
fitToHeight="true" fitToWidth="true">
|
||||||
<VBox.margin>
|
|
||||||
<Insets left="10" right="10"/>
|
|
||||||
</VBox.margin>
|
|
||||||
<VBox>
|
<VBox>
|
||||||
<GridPane fx:id="settingsPane" style="-fx-margin-left: 10; -fx-background-color: white; " hgap="5" vgap="10">
|
<GridPane fx:id="settingsPane" style="-fx-margin-left: 10; -fx-background-color: white; " hgap="5" vgap="10">
|
||||||
<Label GridPane.rowIndex="0" GridPane.columnIndex="0">Java Directory</Label>
|
<Label GridPane.rowIndex="0" GridPane.columnIndex="0">Java Directory</Label>
|
||||||
@@ -105,5 +85,26 @@
|
|||||||
</VBox>
|
</VBox>
|
||||||
</VBox>
|
</VBox>
|
||||||
</ScrollPane>
|
</ScrollPane>
|
||||||
</VBox>
|
</center>
|
||||||
|
<top>
|
||||||
|
<JFXToolbar maxHeight="20" styleClass="jfx-tool-bar">
|
||||||
|
<leftItems>
|
||||||
|
<JFXButton fx:id="backButton" maxHeight="20" styleClass="toggle-icon3"
|
||||||
|
StackPane.alignment="CENTER_LEFT">
|
||||||
|
<graphic>
|
||||||
|
<fx:include source="/assets/svg/arrow-left.fxml" />
|
||||||
|
</graphic>
|
||||||
|
<StackPane.margin>
|
||||||
|
<Insets left="20" />
|
||||||
|
</StackPane.margin>
|
||||||
|
</JFXButton>
|
||||||
|
<Label fx:id="titleLabel" style="-fx-text-fill:WHITE; -fx-font-size: 20;"
|
||||||
|
StackPane.alignment="CENTER_LEFT"/>
|
||||||
|
</leftItems>
|
||||||
|
<rightItems>
|
||||||
|
|
||||||
|
</rightItems>
|
||||||
|
</JFXToolbar>
|
||||||
|
</top>
|
||||||
|
</BorderPane>
|
||||||
</StackPane>
|
</StackPane>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
type="StackPane"
|
type="StackPane"
|
||||||
xmlns:fx="http://javafx.com/fxml">
|
xmlns:fx="http://javafx.com/fxml">
|
||||||
<VBox>
|
<VBox>
|
||||||
<JFXToolbar fx:id="toolbar" maxHeight="20" styleClass="jfx-tool-bar">
|
<JFXToolbar fx:id="toolbar" styleClass="jfx-tool-bar">
|
||||||
<leftItems>
|
<leftItems>
|
||||||
<JFXButton fx:id="closeButton" maxHeight="20" styleClass="toggle-icon3"
|
<JFXButton fx:id="closeButton" maxHeight="20" styleClass="toggle-icon3"
|
||||||
StackPane.alignment="CENTER_RIGHT" onMouseClicked="#close">
|
StackPane.alignment="CENTER_RIGHT" onMouseClicked="#close">
|
||||||
|
|||||||
@@ -52,7 +52,10 @@ interface Scheduler {
|
|||||||
override fun schedule(block: Runnable) = IO_EXECUTOR.submit(block)
|
override fun schedule(block: Runnable) = IO_EXECUTOR.submit(block)
|
||||||
}
|
}
|
||||||
val DEFAULT = NEW_THREAD
|
val DEFAULT = NEW_THREAD
|
||||||
private val CACHED_EXECUTOR = Executors.newCachedThreadPool()
|
private val CACHED_EXECUTOR: ExecutorService by lazy {
|
||||||
|
Executors.newCachedThreadPool()
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user