feat: refine modpack export page look.

This commit is contained in:
huanghongxun
2021-09-18 00:05:33 +08:00
parent d5b4aa5d44
commit aecb100498
6 changed files with 147 additions and 157 deletions

View File

@@ -39,6 +39,8 @@ import javafx.scene.image.ImageView;
import javafx.scene.image.PixelWriter; import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage; import javafx.scene.image.WritableImage;
import javafx.scene.input.*; import javafx.scene.input.*;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region; import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import javafx.scene.shape.Rectangle; import javafx.scene.shape.Rectangle;
@@ -621,6 +623,19 @@ public final class FXUtils {
}; };
} }
public static ColumnConstraints getColumnFillingWidth() {
ColumnConstraints constraint = new ColumnConstraints();
constraint.setFillWidth(true);
return constraint;
}
public static ColumnConstraints getColumnHgrowing() {
ColumnConstraints constraint = new ColumnConstraints();
constraint.setFillWidth(true);
constraint.setHgrow(Priority.ALWAYS);
return constraint;
}
public static final Interpolator SINE = new Interpolator() { public static final Interpolator SINE = new Interpolator() {
@Override @Override
protected double curve(double t) { protected double curve(double t) {

View File

@@ -37,6 +37,10 @@ public class HintPane extends VBox {
private final Text label = new Text(); private final Text label = new Text();
private final StringProperty text = new SimpleStringProperty(this, "text"); private final StringProperty text = new SimpleStringProperty(this, "text");
public HintPane() {
this(MessageDialogPane.MessageType.INFORMATION);
}
public HintPane(MessageDialogPane.MessageType type) { public HintPane(MessageDialogPane.MessageType type) {
setFillWidth(true); setFillWidth(true);
getStyleClass().add("hint"); getStyleClass().add("hint");

View File

@@ -27,11 +27,7 @@ import javafx.geometry.Pos;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.scene.input.MouseEvent; import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane; import javafx.scene.layout.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.TextAlignment;
import javafx.stage.FileChooser; import javafx.stage.FileChooser;
import org.jackhuang.hmcl.Launcher; import org.jackhuang.hmcl.Launcher;
import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.Account;
@@ -47,12 +43,14 @@ import org.jackhuang.hmcl.ui.construct.*;
import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardController;
import org.jackhuang.hmcl.ui.wizard.WizardPage; import org.jackhuang.hmcl.ui.wizard.WizardPage;
import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.jackhuang.hmcl.setting.ConfigHolder.config; import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.ui.FXUtils.jfxListCellFactory; import static org.jackhuang.hmcl.ui.FXUtils.jfxListCellFactory;
@@ -189,10 +187,9 @@ public final class ModpackInfoPage extends Control implements WizardPage {
}); });
borderPane.setTop(hyperlink); borderPane.setTop(hyperlink);
} else { } else {
Label label = new Label(i18n("modpack.wizard.step.initialization.warning")); HintPane pane = new HintPane(MessageDialogPane.MessageType.INFORMATION);
label.setWrapText(true); pane.setText(i18n("modpack.wizard.step.initialization.warning"));
label.setTextAlignment(TextAlignment.JUSTIFY); borderPane.setTop(pane);
borderPane.setTop(label);
} }
{ {
@@ -211,93 +208,137 @@ public final class ModpackInfoPage extends Control implements WizardPage {
} }
{ {
GridPane pane = new GridPane();
list.getContent().add(pane);
pane.setHgap(16);
pane.setVgap(8);
pane.getColumnConstraints().setAll(new ColumnConstraints(), FXUtils.getColumnHgrowing());
int rowIndex = 0;
JFXTextField txtModpackName = new JFXTextField(); JFXTextField txtModpackName = new JFXTextField();
txtModpackName.textProperty().bindBidirectional(skinnable.name); txtModpackName.textProperty().bindBidirectional(skinnable.name);
txtModpackName.setLabelFloat(true);
txtModpackName.setPromptText(i18n("modpack.name"));
txtModpackName.getValidators().add(new RequiredValidator()); txtModpackName.getValidators().add(new RequiredValidator());
StackPane.setMargin(txtModpackName, insets);
list.getContent().add(txtModpackName);
validatingFields.add(txtModpackName); validatingFields.add(txtModpackName);
} pane.addRow(rowIndex++, new Label(i18n("modpack.name")), txtModpackName);
if (skinnable.options.isRequireFileApi()) {
JFXTextField txtModpackFileApi = new JFXTextField();
txtModpackFileApi.textProperty().bindBidirectional(skinnable.fileApi);
txtModpackFileApi.setLabelFloat(true);
txtModpackFileApi.setPromptText(i18n("modpack.file_api"));
if (skinnable.options.isValidateFileApi()) {
txtModpackFileApi.getValidators().add(new RequiredValidator());
}
txtModpackFileApi.getValidators().add(new Validator(s -> {
if (s.isEmpty()) {
return true;
}
try {
new URL(s).toURI();
return true;
} catch (IOException | URISyntaxException e) {
return false;
}
}));
StackPane.setMargin(txtModpackFileApi, insets);
list.getContent().add(txtModpackFileApi);
validatingFields.add(txtModpackFileApi);
}
{
JFXTextField txtModpackAuthor = new JFXTextField(); JFXTextField txtModpackAuthor = new JFXTextField();
txtModpackAuthor.textProperty().bindBidirectional(skinnable.author); txtModpackAuthor.textProperty().bindBidirectional(skinnable.author);
txtModpackAuthor.setLabelFloat(true);
txtModpackAuthor.setPromptText(i18n("archive.author"));
txtModpackAuthor.getValidators().add(new RequiredValidator()); txtModpackAuthor.getValidators().add(new RequiredValidator());
StackPane.setMargin(txtModpackAuthor, insets);
list.getContent().add(txtModpackAuthor);
validatingFields.add(txtModpackAuthor); validatingFields.add(txtModpackAuthor);
} pane.addRow(rowIndex++, new Label(i18n("archive.author")), txtModpackAuthor);
{
JFXTextField txtModpackVersion = new JFXTextField(); JFXTextField txtModpackVersion = new JFXTextField();
txtModpackVersion.textProperty().bindBidirectional(skinnable.version); txtModpackVersion.textProperty().bindBidirectional(skinnable.version);
txtModpackVersion.setLabelFloat(true);
txtModpackVersion.setPromptText(i18n("archive.version"));
txtModpackVersion.getValidators().add(new RequiredValidator()); txtModpackVersion.getValidators().add(new RequiredValidator());
StackPane.setMargin(txtModpackVersion, insets);
list.getContent().add(txtModpackVersion);
validatingFields.add(txtModpackVersion); validatingFields.add(txtModpackVersion);
pane.addRow(rowIndex++, new Label(i18n("archive.version")), txtModpackVersion);
if (skinnable.options.isRequireFileApi()) {
JFXTextField txtModpackFileApi = new JFXTextField();
txtModpackFileApi.textProperty().bindBidirectional(skinnable.fileApi);
validatingFields.add(txtModpackFileApi);
if (skinnable.options.isValidateFileApi()) {
txtModpackFileApi.getValidators().add(new RequiredValidator());
}
txtModpackFileApi.getValidators().add(new Validator(s -> {
if (s.isEmpty()) {
return true;
}
try {
new URL(s).toURI();
return true;
} catch (IOException | URISyntaxException e) {
return false;
}
}));
pane.addRow(rowIndex++, new Label(i18n("modpack.file_api")), txtModpackFileApi);
}
if (skinnable.options.isRequireLaunchArguments()) {
JFXTextField txtLaunchArguments = new JFXTextField();
txtLaunchArguments.textProperty().bindBidirectional(skinnable.launchArguments);
pane.addRow(rowIndex++, new Label(i18n("settings.advanced.minecraft_arguments")), txtLaunchArguments);
}
if (skinnable.options.isRequireJavaArguments()) {
JFXTextField txtJavaArguments = new JFXTextField();
txtJavaArguments.textProperty().bindBidirectional(skinnable.javaArguments);
pane.addRow(rowIndex++, new Label(i18n("settings.advanced.jvm_args")), txtJavaArguments);
}
if (skinnable.options.isRequireUrl()) {
JFXTextField txtModpackUrl = new JFXTextField();
txtModpackUrl.textProperty().bindBidirectional(skinnable.url);
pane.addRow(rowIndex++, new Label(i18n("modpack.origin.url")), txtModpackUrl);
}
if (skinnable.options.isRequireOrigins()) {
JFXTextField txtMcbbs = new JFXTextField();
FXUtils.setValidateWhileTextChanged(txtMcbbs, true);
txtMcbbs.getValidators().add(new NumberValidator(i18n("input.number"), true));
txtMcbbs.textProperty().bindBidirectional(skinnable.mcbbsThreadId);
validatingFields.add(txtMcbbs);
pane.addRow(rowIndex++, new Label(i18n("modpack.origin.mcbbs")), txtMcbbs);
}
}
if (skinnable.options.isRequireMinMemory()) {
VBox pane = new VBox();
Label title = new Label(i18n("settings.memory"));
VBox.setMargin(title, new Insets(0, 0, 8, 0));
HBox lowerBoundPane = new HBox(8);
lowerBoundPane.setAlignment(Pos.CENTER);
VBox.setMargin(lowerBoundPane, new Insets(0, 0, 0, 16));
{
Label label = new Label(i18n("settings.memory.lower_bound"));
JFXSlider slider = new JFXSlider(0, 1, 0);
HBox.setMargin(slider, new Insets(0, 0, 0, 8));
HBox.setHgrow(slider, Priority.ALWAYS);
slider.setValueFactory(self -> Bindings.createStringBinding(() -> (int) (self.getValue() * 100) + "%", self.valueProperty()));
AtomicBoolean changedByTextField = new AtomicBoolean(false);
FXUtils.onChangeAndOperate(skinnable.minMemory, minMemory -> {
changedByTextField.set(true);
slider.setValue(minMemory.intValue() * 1.0 / OperatingSystem.TOTAL_MEMORY);
changedByTextField.set(false);
});
slider.valueProperty().addListener((value, oldVal, newVal) -> {
if (changedByTextField.get()) return;
skinnable.minMemory.set((int) (value.getValue().doubleValue() * OperatingSystem.TOTAL_MEMORY));
});
JFXTextField txtMinMemory = new JFXTextField();
FXUtils.bindInt(txtMinMemory, skinnable.minMemory);
txtMinMemory.getValidators().add(new NumberValidator(i18n("input.number"), false));
FXUtils.setLimitWidth(txtMinMemory, 60);
validatingFields.add(txtMinMemory);
lowerBoundPane.getChildren().setAll(label, slider, txtMinMemory, new Label("MB"));
}
pane.getChildren().setAll(title, lowerBoundPane);
list.getContent().add(pane);
} }
{ {
VBox pane = new VBox(8);
JFXTextArea area = new JFXTextArea(); JFXTextArea area = new JFXTextArea();
area.textProperty().bindBidirectional(skinnable.description); area.textProperty().bindBidirectional(skinnable.description);
area.setLabelFloat(true);
area.setPromptText(i18n("modpack.desc"));
area.setMinHeight(400); area.setMinHeight(400);
StackPane.setMargin(area, insets); pane.getChildren().setAll(new Label(i18n("modpack.desc")), area);
list.getContent().add(area);
}
if (skinnable.options.isRequireForceUpdate()) {
BorderPane pane = new BorderPane();
pane.setLeft(new Label(i18n("modpack.wizard.step.initialization.force_update")));
list.getContent().add(pane); list.getContent().add(pane);
JFXToggleButton button = new JFXToggleButton();
button.selectedProperty().bindBidirectional(skinnable.forceUpdate);
button.setSize(8);
button.setMinHeight(16);
button.setMaxHeight(16);
pane.setRight(button);
} }
if (skinnable.options.isRequireAuthlibInjectorServer()) { if (skinnable.options.isRequireAuthlibInjectorServer()) {
JFXComboBox<AuthlibInjectorServer> cboServers = new JFXComboBox<>(); JFXComboBox<AuthlibInjectorServer> cboServers = new JFXComboBox<>();
cboServers.setMaxWidth(Double.MAX_VALUE);
cboServers.setCellFactory(jfxListCellFactory(server -> new TwoLineListItem(server.getName(), server.getUrl()))); cboServers.setCellFactory(jfxListCellFactory(server -> new TwoLineListItem(server.getName(), server.getUrl())));
cboServers.setConverter(stringConverter(AuthlibInjectorServer::getName)); cboServers.setConverter(stringConverter(AuthlibInjectorServer::getName));
Bindings.bindContent(cboServers.getItems(), config().getAuthlibInjectorServers()); Bindings.bindContent(cboServers.getItems(), config().getAuthlibInjectorServers());
@@ -317,75 +358,17 @@ public final class ModpackInfoPage extends Control implements WizardPage {
list.getContent().add(pane); list.getContent().add(pane);
} }
if (skinnable.options.isRequireMinMemory()) { if (skinnable.options.isRequireForceUpdate()) {
JFXTextField txtMinMemory = new JFXTextField();
FXUtils.bindInt(txtMinMemory, skinnable.minMemory);
txtMinMemory.getValidators().add(new NumberValidator(i18n("input.number"), false));
FXUtils.setLimitWidth(txtMinMemory, 300);
validatingFields.add(txtMinMemory);
BorderPane pane = new BorderPane(); BorderPane pane = new BorderPane();
Label label = new Label(i18n("settings.min_memory")); pane.setLeft(new Label(i18n("modpack.wizard.step.initialization.force_update")));
BorderPane.setAlignment(label, Pos.CENTER_LEFT);
pane.setLeft(label);
BorderPane.setAlignment(txtMinMemory, Pos.CENTER_RIGHT);
pane.setRight(txtMinMemory);
list.getContent().add(pane); list.getContent().add(pane);
}
if (skinnable.options.isRequireLaunchArguments()) { JFXToggleButton button = new JFXToggleButton();
JFXTextField txtLaunchArguments = new JFXTextField(); button.selectedProperty().bindBidirectional(skinnable.forceUpdate);
txtLaunchArguments.textProperty().bindBidirectional(skinnable.launchArguments); button.setSize(8);
txtLaunchArguments.setLabelFloat(true); button.setMinHeight(16);
txtLaunchArguments.setPromptText(i18n("settings.advanced.minecraft_arguments")); button.setMaxHeight(16);
StackPane.setMargin(txtLaunchArguments, insets); pane.setRight(button);
list.getContent().add(txtLaunchArguments);
}
if (skinnable.options.isRequireJavaArguments()) {
JFXTextField txtJavaArguments = new JFXTextField();
txtJavaArguments.textProperty().bindBidirectional(skinnable.javaArguments);
txtJavaArguments.setLabelFloat(true);
txtJavaArguments.setPromptText(i18n("settings.advanced.jvm_args"));
StackPane.setMargin(txtJavaArguments, insets);
list.getContent().add(txtJavaArguments);
}
if (skinnable.options.isRequireOrigins() || skinnable.options.isRequireUrl()) {
BorderPane originPane = new BorderPane();
Label title = new Label(i18n("modpack.origin"));
originPane.setTop(title);
VBox container = new VBox();
BorderPane.setMargin(container, new Insets(0, 0, 0, 16));
originPane.setCenter(container);
list.getContent().add(originPane);
if (skinnable.options.isRequireUrl()) {
BorderPane pane = new BorderPane();
pane.setPadding(new Insets(8, 0, 8, 0));
Label left = new Label(i18n("modpack.origin.url"));
pane.setLeft(left);
JFXTextField txtModpackUrl = new JFXTextField();
txtModpackUrl.textProperty().bindBidirectional(skinnable.url);
pane.setRight(txtModpackUrl);
container.getChildren().add(pane);
}
if (skinnable.options.isRequireOrigins()) {
BorderPane pane = new BorderPane();
pane.setPadding(new Insets(8, 0, 8, 0));
Label left = new Label(i18n("modpack.origin.mcbbs"));
pane.setLeft(left);
JFXTextField txtMcbbs = new JFXTextField();
FXUtils.setValidateWhileTextChanged(txtMcbbs, true);
txtMcbbs.getValidators().add(new NumberValidator(i18n("input.number"), true));
txtMcbbs.textProperty().bindBidirectional(skinnable.mcbbsThreadId);
pane.setRight(txtMcbbs);
container.getChildren().add(pane);
validatingFields.add(txtMcbbs);
}
} }
{ {

View File

@@ -376,13 +376,9 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
customCommandsPane.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not()); customCommandsPane.disableProperty().bind(chkEnableSpecificSettings.selectedProperty().not());
{ {
GridPane pane = new GridPane(); GridPane pane = new GridPane();
ColumnConstraints title = new ColumnConstraints();
ColumnConstraints value = new ColumnConstraints();
value.setFillWidth(true);
value.setHgrow(Priority.ALWAYS);
pane.setHgap(16); pane.setHgap(16);
pane.setVgap(8); pane.setVgap(8);
pane.getColumnConstraints().setAll(title, value); pane.getColumnConstraints().setAll(new ColumnConstraints(), FXUtils.getColumnHgrowing());
txtGameArgs = new JFXTextField(); txtGameArgs = new JFXTextField();
txtGameArgs.setPromptText(i18n("settings.advanced.minecraft_arguments.prompt")); txtGameArgs.setPromptText(i18n("settings.advanced.minecraft_arguments.prompt"));

View File

@@ -237,14 +237,9 @@
} }
.sponsor-pane { .sponsor-pane {
-fx-padding: 16;
-fx-cursor: hand; -fx-cursor: hand;
} }
.sponsor-pane > .label {
-fx-wrap-text: true;
}
/******************************************************************************* /*******************************************************************************
* * * *
* Main Page * * Main Page *

View File

@@ -5,22 +5,19 @@
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import org.jackhuang.hmcl.ui.animation.TransitionPane?> <?import org.jackhuang.hmcl.ui.animation.TransitionPane?>
<?import org.jackhuang.hmcl.ui.construct.ComponentList?> <?import org.jackhuang.hmcl.ui.construct.ComponentList?>
<?import java.lang.String?> <?import org.jackhuang.hmcl.ui.construct.HintPane?>
<?import javafx.geometry.Insets?>
<fx:root xmlns="http://javafx.com/javafx" <fx:root xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml" xmlns:fx="http://javafx.com/fxml"
type="BorderPane" type="BorderPane"
prefHeight="400.0" prefWidth="600.0"> prefHeight="400.0" prefWidth="600.0">
<top> <top>
<VBox> <VBox>
<StackPane style="-fx-padding: 10 10 0 10;"> <HintPane style="-fx-padding: 10 10 0 10;" onMouseClicked="#onSponsor" text="%sponsor.bmclapi" styleClass="sponsor-pane">
<StackPane onMouseClicked="#onSponsor"> <VBox.margin>
<styleClass> <Insets top="10" right="10" left="10" />
<String fx:value="card-non-transparent" /> </VBox.margin>
<String fx:value="sponsor-pane" /> </HintPane>
</styleClass>
<Label text="%sponsor.bmclapi" />
</StackPane>
</StackPane>
</VBox> </VBox>
</top> </top>
<center> <center>