Adding About box. Updated FXControls to allow horizontal or vertical components.

This commit is contained in:
a2geek committed 2026-10-09 12:30:10 -05:00
1 parent 65ba57449a
commit f95b7e37fa
9 files changed
+153 -23

No files matched your search

@@ -7,6 +7,7 @@ module org.applecommander.javafx {
requires org.applecommander.api;
requires org.applecommander.applesingle;
requires org.applecommander.bastools;
requires org.applecommander.shrinkit;
opens org.applecommander.javafx to javafx.graphics;
opens org.applecommander.javafx.settings to javafx.graphics;
@@ -30,9 +30,12 @@ import java.io.PrintWriter;
import java.io.StringWriter;
public class AppleCommanderFX extends Application {
private static AppleCommanderFX application;
@Override
public void start(Stage stage) throws Exception {
// This is really stupid the hoops just to launch the browser.
application = this;
// Based on user selection, use that theme.
Settings.getThemeSelection().orElse(ThemeSelection.MODENA).apply();
Platform.getPreferences().colorSchemeProperty().addListener((_, _, _) -> {
@@ -46,6 +49,10 @@ public class AppleCommanderFX extends Application {
launch(args);
}
public static AppleCommanderFX getApplication() {
return application;
}
public static String buildTitle(String... args) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
@@ -23,11 +23,13 @@ import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import java.util.function.Function;
@@ -35,26 +37,82 @@ import java.util.function.Function;
/// This is a simple control builder for JavaFX components. It is intended to include bindings
/// that reflect the given property.
public class FXControls {
public static FXControls builder() {
return new FXControls();
public static FXControls vertical() {
return new FXControls(new VBox());
}
public static FXControls horizontal() {
return new FXControls(new HBox());
}
private final VBox vbox;
private final Pane pane;
private FXControls() {
vbox = new VBox();
vbox.setSpacing(10);
vbox.setPadding(new Insets(10));
private FXControls(Pane pane) {
this.pane = pane;
spacing(10);
pane.setPadding(new Insets(10));
}
public Node get() {
return vbox;
return pane;
}
public FXControls alignment(Pos value) {
if (pane instanceof VBox vbox) {
vbox.setAlignment(value);
}
else if (pane instanceof HBox hbox) {
hbox.setAlignment(value);
}
return this;
}
public FXControls spacing(double value) {
if (pane instanceof VBox vbox) {
vbox.setSpacing(value);
}
else if (pane instanceof HBox hbox) {
hbox.setSpacing(value);
}
return this;
}
public FXControls node(Node node) {
pane.getChildren().add(node);
return this;
}
public FXControls label(String fmt, Object... args) {
Label label = new Label(String.format(fmt, args));
label.setWrapText(true);
vbox.getChildren().add(label);
pane.getChildren().add(label);
return this;
}
public FXControls link(String text, String url) {
Hyperlink hyperlink = new Hyperlink(url);
hyperlink.setText(text);
hyperlink.setOnAction(event -> {
AppleCommanderFX.getApplication().getHostServices().showDocument(url);
});
pane.getChildren().add(hyperlink);
return this;
}
public FXControls largeBold(String fmt, Object... args) {
Label label = new Label(String.format(fmt, args));
label.setWrapText(true);
label.setStyle("-fx-font-weight: bold; -fx-font-size: 150%");
pane.getChildren().add(label);
return this;
}
public FXControls separator() {
if (pane instanceof VBox vbox) {
vbox.getChildren().add(new Separator(Orientation.HORIZONTAL));
}
else if (pane instanceof HBox hbox) {
hbox.getChildren().add(new Separator(Orientation.VERTICAL));
}
return this;
}
@@ -69,7 +127,7 @@ public class FXControls {
});
radioButton.addEventHandler(ActionEvent.ACTION, _ -> property.set(value));
property.addListener((_, _, newValue) -> radioButton.setSelected(newValue.equals(value)));
vbox.getChildren().add(radioButton);
pane.getChildren().add(radioButton);
}
return this;
}
@@ -80,7 +138,30 @@ public class FXControls {
// We cannot bind this property, need to add listeners in BOTH directions.
checkBox.addEventHandler(ActionEvent.ACTION, _ -> property.set(checkBox.isSelected()));
property.addListener((_, _, newValue) -> checkBox.setSelected(newValue));
vbox.getChildren().add(checkBox);
pane.getChildren().add(checkBox);
return this;
}
public FXControls table(int columnCount, String... values) {
assert values.length % columnCount == 0;
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
grid.setHgap(5);
grid.setVgap(5);
int col = 0;
int row = 0;
for (String value : values) {
Label label = new Label(value);
if (col == 0) label.setStyle("-fx-font-weight: bold;");
else label.setWrapText(true);
grid.add(label, col, row);
col++;
if (col >= columnCount) {
col = 0;
row++;
}
}
pane.getChildren().add(grid);
return this;
}
}
@@ -19,6 +19,7 @@
*/
package org.applecommander.javafx;
import com.webcodepro.applecommander.ui.AppleCommander;
import javafx.beans.property.*;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
@@ -37,12 +38,15 @@ import javafx.scene.shape.Rectangle;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.stage.Stage;
import org.applecommander.applesingle.AppleSingle;
import org.applecommander.bastools.api.BasTools;
import org.applecommander.capability.Capability;
import org.applecommander.filestore.FileStore;
import org.applecommander.filestore.FileStores;
import org.applecommander.javafx.settings.Settings;
import org.applecommander.javafx.settings.SettingsDialog;
import org.applecommander.javafx.wizard.CreateFileStoreWizard;
import org.applecommander.shrinkit.NuFileArchive;
import org.applecommander.source.Source;
import org.applecommander.source.Sources;
import org.applecommander.usage.DiskUsage;
@@ -50,6 +54,7 @@ import org.applecommander.util.FileExtensions;
import org.applecommander.util.FileExtensions.FileExtension;
import java.io.File;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.Objects;
@@ -66,6 +71,7 @@ public class FileStoreWindow {
private final Button saveFileButton;
private final Button saveFileAsButton;
private final Button settingsButton;
private final Button aboutButton;
private final ToggleButton filesViewButton;
private final ToggleButton diskUsageViewButton;
private final ToggleButton informationViewButton;
@@ -146,6 +152,7 @@ public class FileStoreWindow {
saveFileButton = createButton("save-file.png", "Save", _ -> saveFile());
saveFileAsButton = createButton("save-as-file.png", "Save As...", _ -> saveFileAs());
settingsButton = createButton("settings.png", "Settings", _ -> settings());
aboutButton = createButton("about.png", "About", _ -> about());
ToggleGroup viewModeGroup = new ToggleGroup();
filesViewButton = createToggleButton("image-file-view.png", "Files", viewModeGroup, _ -> selectFilesContent());
@@ -154,7 +161,7 @@ public class FileStoreWindow {
HBox viewModeBox = new HBox(filesViewButton, diskUsageViewButton, informationViewButton);
ToolBar toolBar = new ToolBar(
openFileButton, createFileButton, saveFileButton, saveFileAsButton, settingsButton,
openFileButton, createFileButton, saveFileButton, saveFileAsButton, settingsButton, aboutButton,
new Separator(Orientation.VERTICAL),
viewModeBox,
new Separator(Orientation.VERTICAL)
@@ -162,7 +169,7 @@ public class FileStoreWindow {
saveFileButton.disableProperty().bind(changeCount.isEqualTo(0).or(canSave.not()));
ImageView logo = new ImageView(imageUrl("AppleCommanderLogo.png"));
ImageView logo = new ImageView(imageUrl("AppleCommanderLogoLarge.png"));
Label label = new Label("No disk image open. Use open to browse for a disk image.");
label.setTextFill(Color.BLACK);
Rectangle border = new Rectangle();
@@ -372,6 +379,40 @@ public class FileStoreWindow {
dialog.showAndWait(primaryStage);
}
public void about() {
Dialog<ButtonBar.ButtonData> dialog = new Dialog<>();
dialog.setTitle("About AppleCommanderFX");
URL imageURL = getClass().getResource("/images/AppleCommanderLogoSmall.png");
Objects.requireNonNull(imageURL);
ImageView imageView = new ImageView(imageURL.toExternalForm());
VBox imagePane = new VBox(imageView);
imagePane.setPadding(new Insets(0, 0, 10, 0));
imagePane.setStyle("-fx-background-color: white;");
imagePane.setAlignment(Pos.CENTER);
dialog.getDialogPane().setHeader(imagePane);
dialog.getDialogPane().setContent(FXControls.vertical()
.alignment(Pos.CENTER)
.spacing(5)
.largeBold("AppleCommanderFX")
.label("Version %s", AppleCommander.VERSION)
.node(FXControls.horizontal()
.alignment(Pos.CENTER)
.spacing(5)
.label("Visit:")
.link("website", "https://applecommander.github.io/")
.link("github", "https://github.com/AppleCommander/AppleCommander")
.get())
.table(2,
"AppleSingle:", AppleSingle.VERSION,
"ShrinkIt:", NuFileArchive.VERSION,
"BASIC Tools:", BasTools.VERSION)
.get());
dialog.getDialogPane().getButtonTypes().addAll(ButtonType.OK);
dialog.showAndWait();
}
private void switchDisk() {
if (fileStoreSelection.getSelectedIndex()+1 < fileStoreSelection.getItemCount()) {
fileStoreSelection.selectNext();
@@ -47,21 +47,21 @@ public class SettingsDialog {
public SettingsDialog() {
Tab themeTab = new Tab("Theme");
themeTab.setClosable(false);
themeTab.setContent(FXControls.builder()
themeTab.setContent(FXControls.vertical()
.label("Please choose a theme:")
.radioButton(ThemeSelection.values(), ThemeSelection::getDescription, themeSelection)
.get());
Tab exportTab = new Tab("Export");
exportTab.setClosable(false);
exportTab.setContent(FXControls.builder()
exportTab.setContent(FXControls.vertical()
.label("Please select the export type:")
.radioButton(ExportOption.values(), ExportOption::getDescription, exportOption)
.get());
Tab importTab = new Tab("Import");
importTab.setClosable(false);
importTab.setContent(FXControls.builder()
importTab.setContent(FXControls.vertical()
.checkBox("Do you want to decode AppleSingle files on import?", importDecodeAppleSingle)
.checkBox("Do you want to automatically tokenize .bas files as Applesoft?", importTokenizeApplesoft)
.get());
@@ -69,15 +69,15 @@ public class CreateFileStoreWizard extends WizardDialog<CreateFileStoreWizard.Wi
@Override
public Map<WizardPage, Node> createWizardPages() {
return Map.of(
WizardPage.FILESTORE, FXControls.builder()
WizardPage.FILESTORE, FXControls.vertical()
.label("Choose an image type to create:")
.radioButton(FileStoreSelection.values(), FileStoreSelection::getText, fileStoreSelectionProperty)
.get(),
WizardPage.SIZE, FXControls.builder()
WizardPage.SIZE, FXControls.vertical()
.label("Choose an image size to create:")
.radioButton(ImageSizeSelection.values(), ImageSizeSelection::getText, imageSizeSelectionProperty)
.get(),
WizardPage.SECTOR, FXControls.builder()
WizardPage.SECTOR, FXControls.vertical()
.label("Choose a sector ordering for this image:")
.radioButton(SectorOrderSelection.values(), SectorOrderSelection::getText, sectorOrderSelectionProperty)
.get(),
Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B