Rewrite Sampler layout
This commit is contained in:
parent
9438ef66d8
commit
bbec330216
@ -2,6 +2,7 @@
|
||||
|
||||
package atlantafx.base.theme;
|
||||
|
||||
import java.util.Objects;
|
||||
import javafx.css.PseudoClass;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.TabPane;
|
||||
@ -147,4 +148,18 @@ public final class Styles {
|
||||
}
|
||||
node.pseudoClassStateChanged(pseudoClass, true);
|
||||
}
|
||||
|
||||
public static void appendStyle(Node node, String prop, String value) {
|
||||
if (prop == null || prop.isBlank() || value == null || value.isBlank()) {
|
||||
System.err.printf("Ignoring invalid style: property='%s', value='%s'%n", prop, value);
|
||||
return;
|
||||
}
|
||||
|
||||
var style = Objects.requireNonNullElse(node.getStyle(), "");
|
||||
if (!style.endsWith(";")) {
|
||||
style += ";";
|
||||
}
|
||||
style = style + prop.trim() + ":" + value.trim() + ";";
|
||||
node.setStyle(style);
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import javafx.scene.SceneAntialiasing;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyCodeCombination;
|
||||
import javafx.scene.input.KeyCombination;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
@ -38,7 +39,8 @@ public class Launcher extends Application {
|
||||
);
|
||||
|
||||
public static final List<KeyCodeCombination> SUPPORTED_HOTKEYS = List.of(
|
||||
new KeyCodeCombination(KeyCode.SLASH)
|
||||
new KeyCodeCombination(KeyCode.SLASH),
|
||||
new KeyCodeCombination(KeyCode.T, KeyCombination.CONTROL_DOWN)
|
||||
);
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
@ -4,7 +4,7 @@ package atlantafx.sampler.event;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
public class BrowseEvent extends Event {
|
||||
public final class BrowseEvent extends Event {
|
||||
|
||||
private final URI uri;
|
||||
|
||||
|
@ -4,7 +4,7 @@ package atlantafx.sampler.event;
|
||||
|
||||
import javafx.scene.input.KeyCodeCombination;
|
||||
|
||||
public class HotkeyEvent extends Event {
|
||||
public final class HotkeyEvent extends Event {
|
||||
|
||||
private final KeyCodeCombination keys;
|
||||
|
||||
|
28
sampler/src/main/java/atlantafx/sampler/event/PageEvent.java
Normal file
28
sampler/src/main/java/atlantafx/sampler/event/PageEvent.java
Normal file
@ -0,0 +1,28 @@
|
||||
package atlantafx.sampler.event;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class PageEvent extends Event {
|
||||
|
||||
public enum Action {
|
||||
SOURCE_CODE_ON,
|
||||
SOURCE_CODE_OFF
|
||||
}
|
||||
|
||||
private final Action action;
|
||||
|
||||
public PageEvent(Action action) {
|
||||
this.action = Objects.requireNonNull(action, "action");
|
||||
}
|
||||
|
||||
public Action getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ActionEvent{"
|
||||
+ "action=" + action
|
||||
+ "} " + super.toString();
|
||||
}
|
||||
}
|
@ -1,16 +1,6 @@
|
||||
package atlantafx.sampler.event;
|
||||
|
||||
public class ThemeEvent extends Event {
|
||||
|
||||
private final EventType eventType;
|
||||
|
||||
public ThemeEvent(EventType eventType) {
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
public EventType getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
public final class ThemeEvent extends Event {
|
||||
|
||||
public enum EventType {
|
||||
// theme can change both, base font size and colors
|
||||
@ -24,6 +14,16 @@ public class ThemeEvent extends Event {
|
||||
THEME_REMOVE
|
||||
}
|
||||
|
||||
private final EventType eventType;
|
||||
|
||||
public ThemeEvent(EventType eventType) {
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
public EventType getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ThemeEvent{"
|
||||
|
@ -7,7 +7,7 @@ import javafx.geometry.Insets;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.StackPane;
|
||||
|
||||
public class ApplicationWindow extends AnchorPane {
|
||||
public final class ApplicationWindow extends AnchorPane {
|
||||
|
||||
public static final int MIN_WIDTH = 1200;
|
||||
public static final int SIDEBAR_WIDTH = 250;
|
||||
|
@ -1,20 +1,26 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.page;
|
||||
package atlantafx.sampler.layout;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import atlantafx.base.theme.Styles;
|
||||
import atlantafx.sampler.Resources;
|
||||
import atlantafx.sampler.event.DefaultEventBus;
|
||||
import atlantafx.sampler.event.PageEvent;
|
||||
import atlantafx.sampler.theme.HighlightJSTheme;
|
||||
import atlantafx.sampler.util.Containers;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.web.WebView;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2AL;
|
||||
|
||||
public class CodeViewer extends AnchorPane {
|
||||
final class CodeViewer extends AnchorPane {
|
||||
|
||||
private static final String HLJS_LIB = "assets/highlightjs/highlight.min.js";
|
||||
private static final String HLJS_SCRIPT = "hljs.highlightAll();hljs.initLineNumbersOnLoad();";
|
||||
@ -25,6 +31,17 @@ public class CodeViewer extends AnchorPane {
|
||||
private WebView webView;
|
||||
|
||||
public CodeViewer() {
|
||||
super();
|
||||
|
||||
var closeBtn = new Button("Return", new FontIcon(Material2AL.ARROW_BACK));
|
||||
closeBtn.getStyleClass().addAll(Styles.BUTTON_OUTLINED, Styles.SMALL, Styles.ACCENT);
|
||||
AnchorPane.setTopAnchor(closeBtn, 20d);
|
||||
AnchorPane.setRightAnchor(closeBtn, 20d);
|
||||
closeBtn.setOnAction(e ->
|
||||
DefaultEventBus.getInstance().publish(new PageEvent(PageEvent.Action.SOURCE_CODE_OFF))
|
||||
);
|
||||
|
||||
getChildren().add(closeBtn);
|
||||
getStyleClass().add("code-viewer");
|
||||
}
|
||||
|
||||
@ -32,7 +49,7 @@ public class CodeViewer extends AnchorPane {
|
||||
if (webView == null) {
|
||||
webView = new WebView();
|
||||
Containers.setAnchors(webView, Insets.EMPTY);
|
||||
getChildren().setAll(webView);
|
||||
getChildren().add(0, webView);
|
||||
}
|
||||
}
|
||||
|
@ -1,198 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.layout;
|
||||
|
||||
import static atlantafx.base.theme.Styles.TEXT_SMALL;
|
||||
import static atlantafx.base.theme.Styles.TITLE_3;
|
||||
import static atlantafx.base.theme.Styles.TITLE_4;
|
||||
import static atlantafx.sampler.Launcher.IS_DEV_MODE;
|
||||
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.sampler.Resources;
|
||||
import atlantafx.sampler.event.BrowseEvent;
|
||||
import atlantafx.sampler.event.DefaultEventBus;
|
||||
import atlantafx.sampler.event.HotkeyEvent;
|
||||
import java.net.URI;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ContentDisplay;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.text.Text;
|
||||
import org.kordamp.ikonli.Ikon;
|
||||
import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2MZ;
|
||||
import org.kordamp.ikonli.material2.Material2OutlinedMZ;
|
||||
|
||||
class HeaderBar extends HBox {
|
||||
|
||||
private static final int HEADER_HEIGHT = 50;
|
||||
private static final Ikon ICON_CODE = Feather.CODE;
|
||||
private static final Ikon ICON_SAMPLE = Feather.LAYOUT;
|
||||
|
||||
private final MainModel model;
|
||||
private Consumer<Node> quickConfigActionHandler;
|
||||
private Overlay overlay;
|
||||
private SearchDialog searchDialog;
|
||||
|
||||
public HeaderBar(MainModel model) {
|
||||
super();
|
||||
|
||||
this.model = model;
|
||||
|
||||
createView();
|
||||
}
|
||||
|
||||
private void createView() {
|
||||
var logoImage = new ImageView(new Image(Resources.getResource("assets/app-icon.png").toString()));
|
||||
logoImage.setFitWidth(32);
|
||||
logoImage.setFitHeight(32);
|
||||
|
||||
var logoImageBorder = new Insets(1);
|
||||
var logoImageBox = new StackPane(logoImage);
|
||||
logoImageBox.getStyleClass().add("image");
|
||||
logoImageBox.setPadding(logoImageBorder);
|
||||
logoImageBox.setPrefWidth(logoImage.getFitWidth() + logoImageBorder.getRight() * 2);
|
||||
logoImageBox.setMaxWidth(logoImage.getFitHeight() + logoImageBorder.getTop() * 2);
|
||||
logoImageBox.setPrefHeight(logoImage.getFitWidth() + logoImageBorder.getTop() * 2);
|
||||
logoImageBox.setMaxHeight(logoImage.getFitHeight() + logoImageBorder.getRight() * 2);
|
||||
|
||||
var logoLabel = new Label("AtlantaFX");
|
||||
logoLabel.getStyleClass().addAll(TITLE_3);
|
||||
|
||||
var versionLabel = new Label(System.getProperty("app.version"));
|
||||
versionLabel.getStyleClass().addAll("version", TEXT_SMALL);
|
||||
|
||||
var logoBox = new HBox(10, logoImageBox, logoLabel, versionLabel);
|
||||
logoBox.getStyleClass().add("logo");
|
||||
logoBox.setAlignment(Pos.CENTER_LEFT);
|
||||
logoBox.setMinWidth(ApplicationWindow.SIDEBAR_WIDTH);
|
||||
logoBox.setPrefWidth(ApplicationWindow.SIDEBAR_WIDTH);
|
||||
logoBox.setMaxWidth(ApplicationWindow.SIDEBAR_WIDTH);
|
||||
|
||||
var titleLabel = new Label();
|
||||
titleLabel.getStyleClass().addAll("page-title", TITLE_4);
|
||||
titleLabel.textProperty().bind(model.titleProperty());
|
||||
|
||||
var searchBox = new HBox(10,
|
||||
new FontIcon(Material2MZ.SEARCH),
|
||||
new Text("Search"),
|
||||
new Spacer(5),
|
||||
new Label("/")
|
||||
);
|
||||
searchBox.getStyleClass().add("box");
|
||||
searchBox.setAlignment(Pos.CENTER_LEFT);
|
||||
|
||||
var searchButton = new Button();
|
||||
searchButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
|
||||
searchButton.getStyleClass().add("search-button");
|
||||
searchButton.setGraphic(searchBox);
|
||||
searchButton.setOnAction(e -> openSearchDialog());
|
||||
|
||||
DefaultEventBus.getInstance().subscribe(HotkeyEvent.class, e -> {
|
||||
if (e.getKeys().getCode() == KeyCode.SLASH) {
|
||||
openSearchDialog();
|
||||
}
|
||||
});
|
||||
|
||||
// this dummy anchor prevents popover from inheriting
|
||||
// unwanted styles from the owner node
|
||||
var popoverAnchor = new Region();
|
||||
|
||||
var quickConfigBtn = new FontIcon(Material2OutlinedMZ.STYLE);
|
||||
quickConfigBtn.mouseTransparentProperty().bind(model.themeChangeToggleProperty().not());
|
||||
quickConfigBtn.opacityProperty().bind(Bindings.createDoubleBinding(
|
||||
() -> model.themeChangeToggleProperty().get() ? 1.0 : 0.5, model.themeChangeToggleProperty()
|
||||
));
|
||||
quickConfigBtn.setOnMouseClicked(e -> {
|
||||
if (quickConfigActionHandler != null) {
|
||||
quickConfigActionHandler.accept(popoverAnchor);
|
||||
}
|
||||
});
|
||||
|
||||
var sourceCodeBtn = new FontIcon(ICON_CODE);
|
||||
sourceCodeBtn.mouseTransparentProperty().bind(model.sourceCodeToggleProperty().not());
|
||||
sourceCodeBtn.opacityProperty().bind(Bindings.createDoubleBinding(
|
||||
() -> model.sourceCodeToggleProperty().get() ? 1.0 : 0.5, model.sourceCodeToggleProperty()
|
||||
));
|
||||
sourceCodeBtn.setOnMouseClicked(e -> model.nextSubLayer());
|
||||
|
||||
var githubLink = new FontIcon(Feather.GITHUB);
|
||||
githubLink.getStyleClass().addAll("github");
|
||||
githubLink.setOnMouseClicked(e -> {
|
||||
var homepage = System.getProperty("app.homepage");
|
||||
if (homepage != null) {
|
||||
DefaultEventBus.getInstance().publish(new BrowseEvent(URI.create(homepage)));
|
||||
}
|
||||
});
|
||||
|
||||
// ~
|
||||
|
||||
model.currentSubLayerProperty().addListener((obs, old, val) -> {
|
||||
switch (val) {
|
||||
case PAGE -> sourceCodeBtn.setIconCode(ICON_CODE);
|
||||
case SOURCE_CODE -> sourceCodeBtn.setIconCode(ICON_SAMPLE);
|
||||
}
|
||||
});
|
||||
|
||||
setId("header-bar");
|
||||
setMinHeight(HEADER_HEIGHT);
|
||||
setPrefHeight(HEADER_HEIGHT);
|
||||
setAlignment(Pos.CENTER_LEFT);
|
||||
getChildren().setAll(
|
||||
logoBox,
|
||||
titleLabel,
|
||||
new Spacer(),
|
||||
searchButton,
|
||||
popoverAnchor,
|
||||
quickConfigBtn,
|
||||
sourceCodeBtn,
|
||||
githubLink
|
||||
);
|
||||
|
||||
if (IS_DEV_MODE) {
|
||||
var devModeLabel = new Label("app is running in development mode");
|
||||
devModeLabel.getStyleClass().addAll(TEXT_SMALL, "dev-mode-indicator");
|
||||
getChildren().add(2, devModeLabel);
|
||||
}
|
||||
}
|
||||
|
||||
void setQuickConfigActionHandler(Consumer<Node> handler) {
|
||||
this.quickConfigActionHandler = handler;
|
||||
}
|
||||
|
||||
private Overlay lookupOverlay() {
|
||||
return Objects.requireNonNullElse(overlay,
|
||||
overlay = getScene() != null && getScene().lookup("." + Overlay.STYLE_CLASS) instanceof Overlay o ? o : null
|
||||
);
|
||||
}
|
||||
|
||||
private void openSearchDialog() {
|
||||
if (searchDialog == null) {
|
||||
searchDialog = new SearchDialog(model);
|
||||
searchDialog.setOnCloseRequest(() -> {
|
||||
var overlay = lookupOverlay();
|
||||
overlay.removeContent();
|
||||
overlay.toBack();
|
||||
});
|
||||
}
|
||||
|
||||
var overlay = lookupOverlay();
|
||||
overlay.setContent(searchDialog, HPos.CENTER);
|
||||
overlay.toFront();
|
||||
Platform.runLater(() -> searchDialog.begForFocus());
|
||||
}
|
||||
}
|
@ -2,22 +2,19 @@
|
||||
|
||||
package atlantafx.sampler.layout;
|
||||
|
||||
import static atlantafx.base.controls.Popover.ArrowLocation.TOP_CENTER;
|
||||
import static atlantafx.sampler.event.PageEvent.Action;
|
||||
import static javafx.scene.layout.Priority.ALWAYS;
|
||||
|
||||
import atlantafx.base.controls.Popover;
|
||||
import atlantafx.sampler.event.DefaultEventBus;
|
||||
import atlantafx.sampler.event.PageEvent;
|
||||
import atlantafx.sampler.event.ThemeEvent;
|
||||
import atlantafx.sampler.layout.MainModel.SubLayer;
|
||||
import atlantafx.sampler.page.CodeViewer;
|
||||
import atlantafx.sampler.page.Page;
|
||||
import atlantafx.sampler.page.QuickConfigMenu;
|
||||
import atlantafx.sampler.theme.ThemeManager;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import javafx.animation.FadeTransition;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Pane;
|
||||
@ -29,11 +26,9 @@ class MainLayer extends BorderPane {
|
||||
static final int PAGE_TRANSITION_DURATION = 500; // ms
|
||||
|
||||
private final MainModel model = new MainModel();
|
||||
private final HeaderBar headerBar = new HeaderBar(model);
|
||||
private final Sidebar sidebar = new Sidebar(model);
|
||||
private final StackPane subLayerPane = new StackPane();
|
||||
|
||||
private Popover quickConfigPopover;
|
||||
private CodeViewer codeViewer;
|
||||
private StackPane codeViewerWrapper;
|
||||
|
||||
@ -65,14 +60,12 @@ class MainLayer extends BorderPane {
|
||||
// ~
|
||||
|
||||
setId("main");
|
||||
setTop(headerBar);
|
||||
//setTop(headerBar);
|
||||
setLeft(sidebar);
|
||||
setCenter(subLayerPane);
|
||||
}
|
||||
|
||||
private void initListeners() {
|
||||
headerBar.setQuickConfigActionHandler(this::showThemeConfigPopover);
|
||||
|
||||
model.selectedPageProperty().addListener((obs, old, val) -> {
|
||||
if (val != null) {
|
||||
loadPage(val);
|
||||
@ -93,6 +86,16 @@ class MainLayer extends BorderPane {
|
||||
showSourceCode();
|
||||
}
|
||||
});
|
||||
|
||||
// switch to the source code and back
|
||||
DefaultEventBus.getInstance().subscribe(PageEvent.class, e -> {
|
||||
if (e.getAction() == Action.SOURCE_CODE_ON) {
|
||||
model.showSourceCode();
|
||||
}
|
||||
if (e.getAction() == Action.SOURCE_CODE_OFF) {
|
||||
model.hideSourceCode();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadPage(Class<? extends Page> pageClass) {
|
||||
@ -137,21 +140,6 @@ class MainLayer extends BorderPane {
|
||||
}
|
||||
}
|
||||
|
||||
private void showThemeConfigPopover(Node source) {
|
||||
if (quickConfigPopover == null) {
|
||||
var content = new QuickConfigMenu();
|
||||
content.setExitHandler(() -> quickConfigPopover.hide());
|
||||
|
||||
quickConfigPopover = new Popover(content);
|
||||
quickConfigPopover.setHeaderAlwaysVisible(false);
|
||||
quickConfigPopover.setDetachable(false);
|
||||
quickConfigPopover.setArrowLocation(TOP_CENTER);
|
||||
quickConfigPopover.setOnShowing(e -> content.update());
|
||||
}
|
||||
|
||||
quickConfigPopover.show(source);
|
||||
}
|
||||
|
||||
private void showSourceCode() {
|
||||
var sourceClass = Objects.requireNonNull(model.selectedPageProperty().get());
|
||||
var sourceFileName = sourceClass.getSimpleName() + ".java";
|
||||
|
@ -7,21 +7,27 @@ import static atlantafx.sampler.layout.MainModel.SubLayer.SOURCE_CODE;
|
||||
|
||||
import atlantafx.sampler.page.Page;
|
||||
import atlantafx.sampler.page.components.AccordionPage;
|
||||
import atlantafx.sampler.page.components.BreadcrumbsPage;
|
||||
import atlantafx.sampler.page.components.ButtonPage;
|
||||
import atlantafx.sampler.page.components.CalendarPage;
|
||||
import atlantafx.sampler.page.components.ChartPage;
|
||||
import atlantafx.sampler.page.components.CheckBoxPage;
|
||||
import atlantafx.sampler.page.components.ChoiceBoxPage;
|
||||
import atlantafx.sampler.page.components.ColorPickerPage;
|
||||
import atlantafx.sampler.page.components.ComboBoxPage;
|
||||
import atlantafx.sampler.page.components.ContextMenuPage;
|
||||
import atlantafx.sampler.page.components.CustomTextFieldPage;
|
||||
import atlantafx.sampler.page.components.DatePickerPage;
|
||||
import atlantafx.sampler.page.components.DeckPanePage;
|
||||
import atlantafx.sampler.page.components.DialogPage;
|
||||
import atlantafx.sampler.page.components.HtmlEditorPage;
|
||||
import atlantafx.sampler.page.components.LabelPage;
|
||||
import atlantafx.sampler.page.components.InputGroupPage;
|
||||
import atlantafx.sampler.page.components.ListViewPage;
|
||||
import atlantafx.sampler.page.components.MenuBarPage;
|
||||
import atlantafx.sampler.page.components.MenuButtonPage;
|
||||
import atlantafx.sampler.page.components.ModalPanePage;
|
||||
import atlantafx.sampler.page.components.PaginationPage;
|
||||
import atlantafx.sampler.page.components.PopoverPage;
|
||||
import atlantafx.sampler.page.components.ProgressIndicatorPage;
|
||||
import atlantafx.sampler.page.components.RadioButtonPage;
|
||||
import atlantafx.sampler.page.components.ScrollPanePage;
|
||||
@ -35,21 +41,14 @@ import atlantafx.sampler.page.components.TextAreaPage;
|
||||
import atlantafx.sampler.page.components.TextFieldPage;
|
||||
import atlantafx.sampler.page.components.TitledPanePage;
|
||||
import atlantafx.sampler.page.components.ToggleButtonPage;
|
||||
import atlantafx.sampler.page.components.ToggleSwitchPage;
|
||||
import atlantafx.sampler.page.components.ToolBarPage;
|
||||
import atlantafx.sampler.page.components.TooltipPage;
|
||||
import atlantafx.sampler.page.components.TreeTableViewPage;
|
||||
import atlantafx.sampler.page.components.TreeViewPage;
|
||||
import atlantafx.sampler.page.extras.BBCodePage;
|
||||
import atlantafx.sampler.page.extras.BreadcrumbsPage;
|
||||
import atlantafx.sampler.page.extras.CalendarPage;
|
||||
import atlantafx.sampler.page.extras.CustomTextFieldPage;
|
||||
import atlantafx.sampler.page.extras.DeckPanePage;
|
||||
import atlantafx.sampler.page.extras.InputGroupPage;
|
||||
import atlantafx.sampler.page.extras.ModalPanePage;
|
||||
import atlantafx.sampler.page.extras.PopoverPage;
|
||||
import atlantafx.sampler.page.extras.ToggleSwitchPage;
|
||||
import atlantafx.sampler.page.general.BBCodePage;
|
||||
import atlantafx.sampler.page.general.IconsPage;
|
||||
import atlantafx.sampler.page.general.OverviewPage;
|
||||
import atlantafx.sampler.page.showcase.OverviewPage;
|
||||
import atlantafx.sampler.page.general.ThemePage;
|
||||
import atlantafx.sampler.page.general.TypographyPage;
|
||||
import atlantafx.sampler.page.showcase.filemanager.FileManagerPage;
|
||||
@ -72,7 +71,7 @@ import org.kordamp.ikonli.material2.Material2OutlinedMZ;
|
||||
|
||||
public class MainModel {
|
||||
|
||||
public static Class<? extends Page> DEFAULT_PAGE = OverviewPage.class;
|
||||
public static Class<? extends Page> DEFAULT_PAGE = ThemePage.class;
|
||||
|
||||
private static final Map<Class<? extends Page>, NavTree.Item> NAV_TREE = createNavItems();
|
||||
|
||||
@ -144,73 +143,92 @@ public class MainModel {
|
||||
}
|
||||
|
||||
private NavTree.Item createTree() {
|
||||
var general = NavTree.Item.group("General", new FontIcon(Material2OutlinedAL.ARTICLE));
|
||||
var general = NavTree.Item.group("General", new FontIcon(Material2OutlinedMZ.SPEED));
|
||||
general.getChildren().setAll(
|
||||
NAV_TREE.get(OverviewPage.class),
|
||||
NAV_TREE.get(ThemePage.class),
|
||||
NAV_TREE.get(TypographyPage.class),
|
||||
NAV_TREE.get(IconsPage.class)
|
||||
NAV_TREE.get(IconsPage.class),
|
||||
NAV_TREE.get(BBCodePage.class)
|
||||
);
|
||||
general.setExpanded(true);
|
||||
|
||||
var components = NavTree.Item.group("Standard Controls", new FontIcon(Material2OutlinedAL.DASHBOARD));
|
||||
components.getChildren().setAll(
|
||||
var containers = NavTree.Item.group("Containers", new FontIcon(Material2OutlinedMZ.TABLE_CHART));
|
||||
containers.getChildren().setAll(
|
||||
NAV_TREE.get(AccordionPage.class),
|
||||
NAV_TREE.get(ButtonPage.class),
|
||||
NAV_TREE.get(ChartPage.class),
|
||||
NAV_TREE.get(CheckBoxPage.class),
|
||||
NAV_TREE.get(ChoiceBoxPage.class),
|
||||
NAV_TREE.get(ColorPickerPage.class),
|
||||
NAV_TREE.get(ComboBoxPage.class),
|
||||
NAV_TREE.get(ContextMenuPage.class),
|
||||
NAV_TREE.get(DatePickerPage.class),
|
||||
NAV_TREE.get(DialogPage.class),
|
||||
NAV_TREE.get(HtmlEditorPage.class),
|
||||
NAV_TREE.get(LabelPage.class),
|
||||
NAV_TREE.get(ListViewPage.class),
|
||||
NAV_TREE.get(MenuBarPage.class),
|
||||
NAV_TREE.get(MenuButtonPage.class),
|
||||
NAV_TREE.get(PaginationPage.class),
|
||||
NAV_TREE.get(ProgressIndicatorPage.class),
|
||||
NAV_TREE.get(RadioButtonPage.class),
|
||||
NAV_TREE.get(DeckPanePage.class),
|
||||
NAV_TREE.get(ModalPanePage.class),
|
||||
NAV_TREE.get(ScrollPanePage.class),
|
||||
NAV_TREE.get(SeparatorPage.class),
|
||||
NAV_TREE.get(SliderPage.class),
|
||||
NAV_TREE.get(SpinnerPage.class),
|
||||
NAV_TREE.get(SplitPanePage.class),
|
||||
NAV_TREE.get(TableViewPage.class),
|
||||
NAV_TREE.get(TabPanePage.class),
|
||||
NAV_TREE.get(TextAreaPage.class),
|
||||
NAV_TREE.get(TextFieldPage.class),
|
||||
NAV_TREE.get(PopoverPage.class),
|
||||
NAV_TREE.get(TitledPanePage.class),
|
||||
NAV_TREE.get(ToggleButtonPage.class),
|
||||
NAV_TREE.get(ToolBarPage.class),
|
||||
NAV_TREE.get(TooltipPage.class),
|
||||
NAV_TREE.get(ToolBarPage.class)
|
||||
);
|
||||
|
||||
var dataDisplay = NavTree.Item.group("Data Display", new FontIcon(Material2OutlinedAL.LIST_ALT));
|
||||
dataDisplay.getChildren().setAll(
|
||||
NAV_TREE.get(ChartPage.class),
|
||||
NAV_TREE.get(ListViewPage.class),
|
||||
NAV_TREE.get(TableViewPage.class),
|
||||
NAV_TREE.get(TreeTableViewPage.class),
|
||||
NAV_TREE.get(TreeViewPage.class)
|
||||
);
|
||||
|
||||
var extras = NavTree.Item.group("Extras", new FontIcon(Material2OutlinedMZ.TOGGLE_ON));
|
||||
extras.getChildren().setAll(
|
||||
NAV_TREE.get(BBCodePage.class),
|
||||
NAV_TREE.get(BreadcrumbsPage.class),
|
||||
var feedback = NavTree.Item.group("Feedback", new FontIcon(Material2OutlinedAL.CHAT_BUBBLE_OUTLINE));
|
||||
feedback.getChildren().setAll(
|
||||
NAV_TREE.get(DialogPage.class),
|
||||
NAV_TREE.get(ProgressIndicatorPage.class),
|
||||
NAV_TREE.get(TooltipPage.class)
|
||||
);
|
||||
|
||||
var inputs = NavTree.Item.group("Inputs & Controls", new FontIcon(Material2OutlinedAL.EDIT));
|
||||
inputs.getChildren().setAll(
|
||||
NAV_TREE.get(ButtonPage.class),
|
||||
NAV_TREE.get(CalendarPage.class),
|
||||
NAV_TREE.get(CheckBoxPage.class),
|
||||
NAV_TREE.get(ChoiceBoxPage.class),
|
||||
NAV_TREE.get(ColorPickerPage.class),
|
||||
NAV_TREE.get(ComboBoxPage.class),
|
||||
NAV_TREE.get(CustomTextFieldPage.class),
|
||||
NAV_TREE.get(DeckPanePage.class),
|
||||
NAV_TREE.get(DatePickerPage.class),
|
||||
NAV_TREE.get(InputGroupPage.class),
|
||||
NAV_TREE.get(ModalPanePage.class),
|
||||
NAV_TREE.get(PopoverPage.class),
|
||||
NAV_TREE.get(HtmlEditorPage.class),
|
||||
NAV_TREE.get(MenuButtonPage.class),
|
||||
NAV_TREE.get(RadioButtonPage.class),
|
||||
NAV_TREE.get(SliderPage.class),
|
||||
NAV_TREE.get(SpinnerPage.class),
|
||||
NAV_TREE.get(TextAreaPage.class),
|
||||
NAV_TREE.get(TextFieldPage.class),
|
||||
NAV_TREE.get(ToggleButtonPage.class),
|
||||
NAV_TREE.get(ToggleSwitchPage.class)
|
||||
);
|
||||
|
||||
var navigation = NavTree.Item.group("Navigation", new FontIcon(Material2OutlinedMZ.MENU_OPEN));
|
||||
navigation.getChildren().setAll(
|
||||
NAV_TREE.get(BreadcrumbsPage.class),
|
||||
NAV_TREE.get(MenuBarPage.class),
|
||||
NAV_TREE.get(PaginationPage.class),
|
||||
NAV_TREE.get(TabPanePage.class)
|
||||
);
|
||||
|
||||
var showcases = NavTree.Item.group("Showcase", new FontIcon(Material2OutlinedMZ.VISIBILITY));
|
||||
showcases.getChildren().setAll(
|
||||
NAV_TREE.get(OverviewPage.class),
|
||||
NAV_TREE.get(FileManagerPage.class),
|
||||
NAV_TREE.get(MusicPlayerPage.class)
|
||||
);
|
||||
|
||||
var root = NavTree.Item.root();
|
||||
root.getChildren().setAll(general, components, extras, showcases);
|
||||
root.getChildren().setAll(
|
||||
general,
|
||||
containers,
|
||||
dataDisplay,
|
||||
feedback,
|
||||
inputs,
|
||||
navigation,
|
||||
showcases
|
||||
);
|
||||
|
||||
return root;
|
||||
}
|
||||
@ -223,17 +241,19 @@ public class MainModel {
|
||||
var map = new HashMap<Class<? extends Page>, NavTree.Item>();
|
||||
|
||||
// general
|
||||
map.put(OverviewPage.class, NavTree.Item.page(OverviewPage.NAME, OverviewPage.class));
|
||||
map.put(ThemePage.class, NavTree.Item.page(ThemePage.NAME, ThemePage.class));
|
||||
map.put(TypographyPage.class, NavTree.Item.page(TypographyPage.NAME, TypographyPage.class));
|
||||
map.put(
|
||||
TypographyPage.class,
|
||||
NavTree.Item.page(TypographyPage.NAME, TypographyPage.class, "Label", "Hyperlink")
|
||||
);
|
||||
map.put(IconsPage.class, NavTree.Item.page(IconsPage.NAME, IconsPage.class));
|
||||
map.put(BBCodePage.class, NavTree.Item.page(BBCodePage.NAME, BBCodePage.class));
|
||||
|
||||
// components
|
||||
map.put(InputGroupPage.class, NavTree.Item.page(InputGroupPage.NAME, InputGroupPage.class));
|
||||
map.put(AccordionPage.class, NavTree.Item.page(AccordionPage.NAME, AccordionPage.class));
|
||||
map.put(BreadcrumbsPage.class, NavTree.Item.page(BreadcrumbsPage.NAME, BreadcrumbsPage.class));
|
||||
map.put(ButtonPage.class, NavTree.Item.page(ButtonPage.NAME, ButtonPage.class));
|
||||
map.put(BBCodePage.class, NavTree.Item.page(BBCodePage.NAME, BBCodePage.class));
|
||||
map.put(CalendarPage.class, NavTree.Item.page(CalendarPage.NAME, CalendarPage.class));
|
||||
map.put(ChartPage.class, NavTree.Item.page(ChartPage.NAME, ChartPage.class));
|
||||
map.put(ChoiceBoxPage.class, NavTree.Item.page(ChoiceBoxPage.NAME, ChoiceBoxPage.class));
|
||||
@ -246,13 +266,15 @@ public class MainModel {
|
||||
map.put(ContextMenuPage.class, NavTree.Item.page(ContextMenuPage.NAME, ContextMenuPage.class));
|
||||
map.put(
|
||||
CustomTextFieldPage.class,
|
||||
NavTree.Item.page(CustomTextFieldPage.NAME, CustomTextFieldPage.class, "MaskTextField", "PasswordTextField")
|
||||
NavTree.Item.page(
|
||||
CustomTextFieldPage.NAME, CustomTextFieldPage.class,
|
||||
"MaskTextField", "PasswordTextField"
|
||||
)
|
||||
);
|
||||
map.put(DatePickerPage.class, NavTree.Item.page(DatePickerPage.NAME, DatePickerPage.class));
|
||||
map.put(DeckPanePage.class, NavTree.Item.page(DeckPanePage.NAME, DeckPanePage.class));
|
||||
map.put(DialogPage.class, NavTree.Item.page(DialogPage.NAME, DialogPage.class));
|
||||
map.put(HtmlEditorPage.class, NavTree.Item.page(HtmlEditorPage.NAME, HtmlEditorPage.class));
|
||||
map.put(LabelPage.class, NavTree.Item.page(LabelPage.NAME, LabelPage.class));
|
||||
map.put(ListViewPage.class, NavTree.Item.page(ListViewPage.NAME, ListViewPage.class));
|
||||
map.put(MenuBarPage.class, NavTree.Item.page(MenuBarPage.NAME, MenuBarPage.class));
|
||||
map.put(MenuButtonPage.class, NavTree.Item.page(
|
||||
@ -288,6 +310,7 @@ public class MainModel {
|
||||
map.put(TreeViewPage.class, NavTree.Item.page(TreeViewPage.NAME, TreeViewPage.class));
|
||||
|
||||
// showcases
|
||||
map.put(OverviewPage.class, NavTree.Item.page(OverviewPage.NAME, OverviewPage.class));
|
||||
map.put(FileManagerPage.class, NavTree.Item.page(FileManagerPage.NAME, FileManagerPage.class));
|
||||
map.put(MusicPlayerPage.class, NavTree.Item.page(MusicPlayerPage.NAME, MusicPlayerPage.class));
|
||||
|
||||
@ -309,8 +332,11 @@ public class MainModel {
|
||||
currentSubLayer.set(PAGE);
|
||||
}
|
||||
|
||||
public void nextSubLayer() {
|
||||
var old = currentSubLayer.get();
|
||||
currentSubLayer.set(old == PAGE ? SOURCE_CODE : PAGE);
|
||||
public void showSourceCode() {
|
||||
currentSubLayer.set(SOURCE_CODE);
|
||||
}
|
||||
|
||||
public void hideSourceCode() {
|
||||
currentSubLayer.set(PAGE);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import java.util.Objects;
|
||||
import javafx.scene.Node;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public record Nav(String title,
|
||||
record Nav(String title,
|
||||
@Nullable Node graphic,
|
||||
@Nullable Class<? extends Page> pageClass,
|
||||
@Nullable List<String> searchKeywords) {
|
||||
|
@ -3,6 +3,7 @@
|
||||
package atlantafx.sampler.layout;
|
||||
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.base.theme.Tweaks;
|
||||
import atlantafx.sampler.page.Page;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@ -20,7 +21,7 @@ import javafx.scene.layout.HBox;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
public class NavTree extends TreeView<Nav> {
|
||||
final class NavTree extends TreeView<Nav> {
|
||||
|
||||
public NavTree(MainModel model) {
|
||||
super();
|
||||
@ -35,6 +36,7 @@ public class NavTree extends TreeView<Nav> {
|
||||
}
|
||||
});
|
||||
|
||||
getStyleClass().addAll(Tweaks.EDGE_TO_EDGE);
|
||||
setShowRoot(false);
|
||||
rootProperty().bind(model.navTreeProperty());
|
||||
setCellFactory(p -> new NavTreeCell());
|
||||
|
@ -24,7 +24,7 @@ import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.util.Duration;
|
||||
|
||||
public class Overlay extends StackPane {
|
||||
public final class Overlay extends StackPane {
|
||||
|
||||
public static final String STYLE_CLASS = "overlay";
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.page;
|
||||
package atlantafx.sampler.layout;
|
||||
|
||||
import static atlantafx.base.theme.Styles.BUTTON_CIRCLE;
|
||||
import static atlantafx.base.theme.Styles.BUTTON_ICON;
|
@ -6,7 +6,6 @@ import atlantafx.base.controls.CustomTextField;
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import atlantafx.base.theme.Tweaks;
|
||||
import atlantafx.sampler.page.OverlayDialog;
|
||||
import java.util.function.Consumer;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
|
@ -2,34 +2,233 @@
|
||||
|
||||
package atlantafx.sampler.layout;
|
||||
|
||||
import static atlantafx.base.theme.Styles.TEXT_BOLD;
|
||||
import static atlantafx.base.theme.Styles.TEXT_MUTED;
|
||||
import static atlantafx.base.theme.Styles.TEXT_SMALL;
|
||||
import static atlantafx.base.theme.Styles.TEXT_SUBTLE;
|
||||
import static atlantafx.base.theme.Styles.TITLE_3;
|
||||
import static atlantafx.sampler.Launcher.IS_DEV_MODE;
|
||||
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import atlantafx.sampler.Resources;
|
||||
import atlantafx.sampler.event.BrowseEvent;
|
||||
import atlantafx.sampler.event.DefaultEventBus;
|
||||
import atlantafx.sampler.event.HotkeyEvent;
|
||||
import atlantafx.sampler.util.Lazy;
|
||||
import java.net.URI;
|
||||
import java.util.Objects;
|
||||
import javafx.application.Platform;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Cursor;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ContentDisplay;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyCodeCombination;
|
||||
import javafx.scene.input.KeyCombination;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2MZ;
|
||||
import org.kordamp.ikonli.material2.Material2OutlinedAL;
|
||||
|
||||
class Sidebar extends StackPane {
|
||||
final class Sidebar extends VBox {
|
||||
|
||||
private final MainModel model;
|
||||
private final NavTree navTree;
|
||||
private Overlay overlay;
|
||||
private final Lazy<SearchDialog> searchDialog;
|
||||
private final Lazy<ThemeDialog> themeDialog;
|
||||
|
||||
public Sidebar(MainModel model) {
|
||||
super();
|
||||
|
||||
this.model = model;
|
||||
this.navTree = new NavTree(model);
|
||||
|
||||
createView();
|
||||
}
|
||||
|
||||
private void createView() {
|
||||
searchDialog = new Lazy<>(() -> {
|
||||
var dialog = new SearchDialog(model);
|
||||
dialog.setOnCloseRequest(() -> {
|
||||
var overlay = lookupOverlay();
|
||||
overlay.removeContent();
|
||||
overlay.toBack();
|
||||
});
|
||||
return dialog;
|
||||
});
|
||||
|
||||
themeDialog = new Lazy<>(() -> {
|
||||
var dialog = new ThemeDialog();
|
||||
dialog.setOnCloseRequest(() -> {
|
||||
var overlay = lookupOverlay();
|
||||
overlay.removeContent();
|
||||
overlay.toBack();
|
||||
});
|
||||
return dialog;
|
||||
});
|
||||
|
||||
model.selectedPageProperty().addListener((obs, old, val) -> {
|
||||
if (val != null) {
|
||||
navTree.getSelectionModel().select(model.getTreeItemForPage(val));
|
||||
}
|
||||
});
|
||||
|
||||
DefaultEventBus.getInstance().subscribe(HotkeyEvent.class, e -> {
|
||||
if (e.getKeys().getCode() == KeyCode.SLASH) {
|
||||
openSearchDialog();
|
||||
}
|
||||
});
|
||||
|
||||
var themeKeys = new KeyCodeCombination(KeyCode.T, KeyCombination.CONTROL_DOWN);
|
||||
DefaultEventBus.getInstance().subscribe(HotkeyEvent.class, e -> {
|
||||
if (Objects.equals(e.getKeys(), themeKeys)) {
|
||||
openThemeDialog();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void createView() {
|
||||
var header = new Header();
|
||||
|
||||
VBox.setVgrow(navTree, Priority.ALWAYS);
|
||||
|
||||
setId("sidebar");
|
||||
getChildren().addAll(navTree);
|
||||
getChildren().addAll(header, navTree, createFooter());
|
||||
}
|
||||
|
||||
void begForFocus() {
|
||||
navTree.requestFocus();
|
||||
}
|
||||
|
||||
private HBox createFooter() {
|
||||
var versionLbl = new Label("v" + System.getProperty("app.version"));
|
||||
versionLbl.getStyleClass().addAll(
|
||||
"version", TEXT_SMALL, TEXT_BOLD, TEXT_SUBTLE
|
||||
);
|
||||
versionLbl.setCursor(Cursor.HAND);
|
||||
versionLbl.setOnMouseClicked(e -> {
|
||||
var homepage = System.getProperty("app.homepage");
|
||||
if (homepage != null) {
|
||||
DefaultEventBus.getInstance().publish(new BrowseEvent(URI.create(homepage)));
|
||||
}
|
||||
});
|
||||
versionLbl.setTooltip(new Tooltip("Visit homepage"));
|
||||
|
||||
var footer = new HBox(versionLbl);
|
||||
footer.getStyleClass().add("footer");
|
||||
|
||||
return footer;
|
||||
}
|
||||
|
||||
private void openSearchDialog() {
|
||||
var dialog = searchDialog.get();
|
||||
var overlay = lookupOverlay();
|
||||
overlay.setContent(dialog, HPos.CENTER);
|
||||
overlay.toFront();
|
||||
Platform.runLater(dialog::begForFocus);
|
||||
}
|
||||
|
||||
private void openThemeDialog() {
|
||||
var dialog = themeDialog.get();
|
||||
var overlay = lookupOverlay();
|
||||
overlay.setContent(dialog, HPos.CENTER);
|
||||
overlay.toFront();
|
||||
Platform.runLater(dialog::requestFocus);
|
||||
}
|
||||
|
||||
private Overlay lookupOverlay() {
|
||||
return Objects.requireNonNullElse(overlay,
|
||||
overlay = getScene() != null
|
||||
&& getScene().lookup("." + Overlay.STYLE_CLASS) instanceof Overlay o ? o : null
|
||||
);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private class Header extends VBox {
|
||||
|
||||
public Header() {
|
||||
super();
|
||||
|
||||
getStyleClass().add("header");
|
||||
getChildren().setAll(
|
||||
createLogo(), createSearchButton()
|
||||
);
|
||||
}
|
||||
|
||||
private HBox createLogo() {
|
||||
var image = new ImageView(
|
||||
new Image(Resources.getResource("assets/app-icon.png").toString())
|
||||
);
|
||||
image.setFitWidth(32);
|
||||
image.setFitHeight(32);
|
||||
|
||||
var imageBorder = new Insets(1);
|
||||
var imageBox = new StackPane(image);
|
||||
imageBox.getStyleClass().add("image");
|
||||
imageBox.setPadding(imageBorder);
|
||||
imageBox.setPrefSize(
|
||||
image.getFitWidth() + imageBorder.getRight() * 2,
|
||||
image.getFitWidth() + imageBorder.getTop() * 2
|
||||
);
|
||||
imageBox.setMaxSize(
|
||||
image.getFitHeight() + imageBorder.getTop() * 2,
|
||||
image.getFitHeight() + imageBorder.getRight() * 2
|
||||
);
|
||||
|
||||
var titleLbl = new Label("AtlantaFX");
|
||||
titleLbl.getStyleClass().addAll(TITLE_3);
|
||||
if (IS_DEV_MODE) {
|
||||
var devLabel = new Label();
|
||||
devLabel.setGraphic(new FontIcon(Material2OutlinedAL.INFO));
|
||||
devLabel.getStyleClass().addAll("dev-indicator", Styles.WARNING);
|
||||
devLabel.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
|
||||
devLabel.setTooltip(new Tooltip("App is running in development mode"));
|
||||
|
||||
titleLbl.setContentDisplay(ContentDisplay.RIGHT);
|
||||
titleLbl.setGraphic(devLabel);
|
||||
}
|
||||
|
||||
var themeSwitchBtn = new Button();
|
||||
themeSwitchBtn.getStyleClass().add("palette");
|
||||
themeSwitchBtn.setGraphic(new FontIcon(Material2MZ.WB_SUNNY));
|
||||
themeSwitchBtn.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
|
||||
themeSwitchBtn.getStyleClass().addAll(Styles.BUTTON_CIRCLE, Styles.FLAT);
|
||||
themeSwitchBtn.setAlignment(Pos.CENTER_RIGHT);
|
||||
themeSwitchBtn.setOnAction(e -> openThemeDialog());
|
||||
|
||||
var root = new HBox(10, imageBox, titleLbl, new Spacer(), themeSwitchBtn);
|
||||
root.getStyleClass().add("logo");
|
||||
root.setAlignment(Pos.CENTER_LEFT);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private Button createSearchButton() {
|
||||
var titleLbl = new Label("Search", new FontIcon(Material2MZ.SEARCH));
|
||||
|
||||
var hintLbl = new Label("Press /");
|
||||
hintLbl.getStyleClass().addAll("hint", TEXT_MUTED, TEXT_SMALL);
|
||||
|
||||
var searchBox = new HBox(titleLbl, new Spacer(), hintLbl);
|
||||
searchBox.getStyleClass().add("content");
|
||||
searchBox.setAlignment(Pos.CENTER_LEFT);
|
||||
|
||||
var root = new Button();
|
||||
root.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
|
||||
root.getStyleClass().addAll("search-button");
|
||||
root.setGraphic(searchBox);
|
||||
root.setOnAction(e -> openSearchDialog());
|
||||
root.setMaxWidth(Double.MAX_VALUE);
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
package atlantafx.sampler.layout;
|
||||
|
||||
import atlantafx.sampler.theme.SamplerTheme;
|
||||
import atlantafx.sampler.theme.ThemeManager;
|
||||
import atlantafx.sampler.util.NodeUtils;
|
||||
import java.util.Objects;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.layout.TilePane;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
final class ThemeDialog extends OverlayDialog<VBox> {
|
||||
|
||||
private final TilePane thumbnailsPane = new TilePane(20, 20);
|
||||
private final ToggleGroup thumbnailsGroup = new ToggleGroup();
|
||||
|
||||
public ThemeDialog() {
|
||||
super();
|
||||
|
||||
setId("theme-dialog");
|
||||
setTitle("Select a theme");
|
||||
setContent(createContent());
|
||||
NodeUtils.toggleVisibility(footerBox, false);
|
||||
|
||||
updateThumbnails();
|
||||
|
||||
thumbnailsGroup.selectedToggleProperty().addListener((obs, old, val) -> {
|
||||
System.out.println(0);
|
||||
System.out.println(val.getUserData().getClass().getName());
|
||||
if (val != null && val.getUserData() instanceof SamplerTheme theme) {
|
||||
System.out.println(1);
|
||||
ThemeManager.getInstance().setTheme(theme);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private VBox createContent() {
|
||||
thumbnailsPane.setAlignment(Pos.TOP_CENTER);
|
||||
thumbnailsPane.setPrefColumns(3);
|
||||
thumbnailsPane.setStyle("-color-thumbnail-border:-color-border-subtle;");
|
||||
|
||||
var root = new VBox(thumbnailsPane);
|
||||
root.setPadding(new Insets(20));
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void updateThumbnails() {
|
||||
var tm = ThemeManager.getInstance();
|
||||
|
||||
thumbnailsPane.getChildren().clear();
|
||||
tm.getRepository().getAll().forEach(theme -> {
|
||||
var thumbnail = new ThemeThumbnail(theme);
|
||||
thumbnail.setToggleGroup(thumbnailsGroup);
|
||||
thumbnail.setUserData(theme);
|
||||
thumbnail.setSelected(Objects.equals(
|
||||
tm.getTheme().getName(),
|
||||
theme.getName()
|
||||
));
|
||||
thumbnailsPane.getChildren().add(thumbnail);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package atlantafx.sampler.layout;
|
||||
|
||||
import atlantafx.base.theme.Styles;
|
||||
import atlantafx.sampler.theme.SamplerTheme;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.css.PseudoClass;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.RadioButton;
|
||||
import javafx.scene.control.Toggle;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.shape.Circle;
|
||||
|
||||
public final class ThemeThumbnail extends VBox implements Toggle {
|
||||
|
||||
private static final PseudoClass SELECTED = PseudoClass.getPseudoClass("selected");
|
||||
private final RadioButton toggle; // internal helper node to manage selected state
|
||||
|
||||
public ThemeThumbnail(SamplerTheme theme) {
|
||||
super();
|
||||
|
||||
toggle = new RadioButton();
|
||||
|
||||
try {
|
||||
Map<String, String> colors = theme.parseColors();
|
||||
|
||||
var circles = new HBox(
|
||||
createCircle(colors.get("-color-fg-default"), colors.get("-color-fg-default"), false),
|
||||
createCircle(colors.get("-color-fg-default"), colors.get("-color-accent-emphasis"), true),
|
||||
createCircle(colors.get("-color-fg-default"), colors.get("-color-success-emphasis"), true),
|
||||
createCircle(colors.get("-color-fg-default"), colors.get("-color-danger-emphasis"), true),
|
||||
createCircle(colors.get("-color-fg-default"), colors.get("-color-warning-emphasis"), true)
|
||||
);
|
||||
circles.setAlignment(Pos.CENTER);
|
||||
|
||||
var nameLbl = new Label(theme.getName());
|
||||
nameLbl.getStyleClass().add(Styles.TEXT_CAPTION);
|
||||
Styles.appendStyle(nameLbl, "-fx-text-fill", colors.get("-color-fg-muted"));
|
||||
|
||||
setStyle("""
|
||||
-fx-background-radius: 10px, 8px;
|
||||
-fx-background-insets: 0, 3px
|
||||
"""
|
||||
);
|
||||
Styles.appendStyle(
|
||||
this,
|
||||
"-fx-background-color",
|
||||
"-color-thumbnail-border," + colors.get("-color-bg-default")
|
||||
);
|
||||
setOnMouseClicked(e -> setSelected(true));
|
||||
getStyleClass().add("theme-thumbnail");
|
||||
getChildren().setAll(nameLbl, circles);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
selectedProperty().addListener(
|
||||
(obs, old, val) -> pseudoClassStateChanged(SELECTED, val)
|
||||
);
|
||||
}
|
||||
|
||||
private Circle createCircle(String borderColor, String bgColor, boolean overlap) {
|
||||
var circle = new Circle(10);
|
||||
Styles.appendStyle(circle, "-fx-stroke", borderColor);
|
||||
Styles.appendStyle(circle, "-fx-fill", bgColor);
|
||||
if (overlap) {
|
||||
HBox.setMargin(circle, new Insets(0, 0, 0, -5));
|
||||
}
|
||||
return circle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ToggleGroup getToggleGroup() {
|
||||
return toggle.getToggleGroup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setToggleGroup(ToggleGroup toggleGroup) {
|
||||
toggle.setToggleGroup(toggleGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectProperty<ToggleGroup> toggleGroupProperty() {
|
||||
return toggle.toggleGroupProperty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected() {
|
||||
return toggle.isSelected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(boolean selected) {
|
||||
toggle.setSelected(selected);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BooleanProperty selectedProperty() {
|
||||
return toggle.selectedProperty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserData(Object value) {
|
||||
toggle.setUserData(value);
|
||||
}
|
||||
}
|
@ -8,14 +8,14 @@ import static javafx.scene.control.ScrollPane.ScrollBarPolicy.NEVER;
|
||||
|
||||
import atlantafx.base.util.BBCodeParser;
|
||||
import atlantafx.sampler.layout.Overlay;
|
||||
import java.net.URI;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class AbstractPage extends StackPane implements Page {
|
||||
|
||||
@ -45,10 +45,6 @@ public abstract class AbstractPage extends StackPane implements Page {
|
||||
getChildren().setAll(scrollPane);
|
||||
}
|
||||
|
||||
protected void setUserContent(Node content) {
|
||||
userContent.getChildren().setAll(content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pane getView() {
|
||||
return this;
|
||||
@ -64,6 +60,11 @@ public abstract class AbstractPage extends StackPane implements Page {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable URI getJavadocUri() {
|
||||
return URI.create(String.format(JFX_JAVADOC_URI_TEMPLATE, "control/" + getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
}
|
||||
@ -85,12 +86,13 @@ public abstract class AbstractPage extends StackPane implements Page {
|
||||
this.overlay = lookupOverlay();
|
||||
}
|
||||
|
||||
protected void addNode(Node node) {
|
||||
userContent.getChildren().add(node);
|
||||
protected void addPageHeader() {
|
||||
var pageHeader = new PageHeader(this);
|
||||
userContent.getChildren().add(pageHeader);
|
||||
}
|
||||
|
||||
protected void addPlainText(String text) {
|
||||
userContent.getChildren().add(new TextFlow(new Text(text)));
|
||||
protected void addNode(Node node) {
|
||||
userContent.getChildren().add(node);
|
||||
}
|
||||
|
||||
protected void addFormattedText(String text) {
|
||||
|
@ -8,7 +8,7 @@ import javafx.scene.text.TextFlow;
|
||||
|
||||
// This code is adapted from RichTextFX JavaKeywordsDemo:
|
||||
// https://github.com/FXMisc/RichTextFX/blob/master/richtextfx-demos
|
||||
public class BBSyntaxHighlighter {
|
||||
public final class BBSyntaxHighlighter {
|
||||
|
||||
private static final String[] KEYWORDS = new String[] {
|
||||
"abstract", "assert", "boolean", "break", "byte",
|
||||
|
@ -23,7 +23,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
// This widget emulates TabPane behavior, because TabPane itself doesn't work as it should:
|
||||
// https://bugs.openjdk.org/browse/JDK-8145490
|
||||
public class ExampleBox extends VBox {
|
||||
public final class ExampleBox extends VBox {
|
||||
|
||||
private static final PseudoClass SELECTED = PseudoClass.getPseudoClass("selected");
|
||||
private final ObjectProperty<Label> selectedTab = new SimpleObjectProperty<>();
|
||||
|
@ -8,6 +8,7 @@ import static javafx.scene.control.ScrollPane.ScrollBarPolicy.NEVER;
|
||||
|
||||
import atlantafx.base.theme.Styles;
|
||||
import atlantafx.sampler.layout.Overlay;
|
||||
import java.net.URI;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
@ -26,7 +27,6 @@ import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
@ -126,12 +126,13 @@ public abstract class OutlinePage extends StackPane implements Page {
|
||||
return lastHeading != null ? lastHeading.getText() : null;
|
||||
}
|
||||
|
||||
protected void addNode(Node node) {
|
||||
userContent.getChildren().add(node);
|
||||
protected void addPageHeader() {
|
||||
var pageHeader = new PageHeader(this);
|
||||
userContent.getChildren().add(pageHeader);
|
||||
}
|
||||
|
||||
protected void addPlainText(String text) {
|
||||
userContent.getChildren().add(new TextFlow(new Text(text)));
|
||||
protected void addNode(Node node) {
|
||||
userContent.getChildren().add(node);
|
||||
}
|
||||
|
||||
protected void addFormattedText(String text) {
|
||||
@ -171,6 +172,11 @@ public abstract class OutlinePage extends StackPane implements Page {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable URI getJavadocUri() {
|
||||
return URI.create(String.format(JFX_JAVADOC_URI_TEMPLATE, "control/" + getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
}
|
||||
|
@ -2,12 +2,18 @@
|
||||
|
||||
package atlantafx.sampler.page;
|
||||
|
||||
import static javafx.scene.input.KeyCombination.ALT_DOWN;
|
||||
|
||||
import atlantafx.base.theme.Styles;
|
||||
import atlantafx.base.theme.Tweaks;
|
||||
import atlantafx.base.util.BBCodeParser;
|
||||
import atlantafx.sampler.event.BrowseEvent;
|
||||
import atlantafx.sampler.event.DefaultEventBus;
|
||||
import atlantafx.sampler.event.PageEvent;
|
||||
import atlantafx.sampler.layout.ApplicationWindow;
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
@ -16,8 +22,16 @@ import javafx.scene.Node;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.MenuButton;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyCodeCombination;
|
||||
import javafx.scene.layout.HBox;
|
||||
import net.datafaker.Faker;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2AL;
|
||||
|
||||
public interface Page {
|
||||
|
||||
@ -29,8 +43,10 @@ public interface Page {
|
||||
|
||||
Faker FAKER = new Faker();
|
||||
Random RANDOM = new Random();
|
||||
int PAGE_HGAP = 30;
|
||||
int PAGE_VGAP = 30;
|
||||
String JFX_JAVADOC_URI_TEMPLATE =
|
||||
"https://openjfx.io/javadoc/20/javafx.controls/javafx/scene/%s.html";
|
||||
String AFX_JAVADOC_URI_TEMPLATE =
|
||||
"https://mkpaz.github.io/atlantafx/apidocs/atlantafx.base/atlantafx/base/%s.html";
|
||||
|
||||
String getName();
|
||||
|
||||
@ -40,6 +56,8 @@ public interface Page {
|
||||
|
||||
boolean canChangeThemeSettings();
|
||||
|
||||
@Nullable URI getJavadocUri();
|
||||
|
||||
void reset();
|
||||
|
||||
default <T> List<T> generate(Supplier<T> supplier, int count) {
|
||||
@ -72,4 +90,43 @@ public interface Page {
|
||||
label.setStyle("-fx-font-family:monospace");
|
||||
return label;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class PageHeader extends HBox {
|
||||
|
||||
public PageHeader(Page page) {
|
||||
super();
|
||||
|
||||
Objects.requireNonNull(page, "page");
|
||||
|
||||
var titleLbl = new Label(page.getName());
|
||||
titleLbl.getStyleClass().add(Styles.TITLE_2);
|
||||
|
||||
var sourceCodeItem = new MenuItem("Source Code", new FontIcon(Feather.CODE));
|
||||
sourceCodeItem.setDisable(!page.canDisplaySourceCode());
|
||||
sourceCodeItem.setAccelerator(new KeyCodeCombination(KeyCode.C, ALT_DOWN));
|
||||
sourceCodeItem.setOnAction(e ->
|
||||
DefaultEventBus.getInstance().publish(new PageEvent(PageEvent.Action.SOURCE_CODE_ON))
|
||||
);
|
||||
|
||||
final var uri = page.getJavadocUri();
|
||||
var javadocItem = new MenuItem("Javadoc", new FontIcon(Feather.COFFEE));
|
||||
javadocItem.setAccelerator(new KeyCodeCombination(KeyCode.J, ALT_DOWN));
|
||||
javadocItem.setDisable(uri == null);
|
||||
javadocItem.setOnAction(e -> {
|
||||
if (uri != null) {
|
||||
DefaultEventBus.getInstance().publish(new BrowseEvent(uri));
|
||||
}
|
||||
});
|
||||
|
||||
var menuBtn = new MenuButton("", new FontIcon(Material2AL.EXPAND_MORE));
|
||||
menuBtn.getStyleClass().addAll(Styles.FLAT, Styles.BUTTON_ICON, Tweaks.NO_ARROW);
|
||||
menuBtn.getItems().setAll(sourceCodeItem, javadocItem);
|
||||
|
||||
getStyleClass().add("header");
|
||||
setSpacing(20);
|
||||
getChildren().setAll(titleLbl, menuBtn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,252 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.page;
|
||||
|
||||
import static atlantafx.base.theme.Styles.BUTTON_CIRCLE;
|
||||
import static atlantafx.base.theme.Styles.BUTTON_ICON;
|
||||
import static atlantafx.base.theme.Styles.FLAT;
|
||||
import static atlantafx.base.theme.Styles.TEXT_CAPTION;
|
||||
import static atlantafx.sampler.theme.ThemeManager.DEFAULT_ZOOM;
|
||||
import static atlantafx.sampler.theme.ThemeManager.SUPPORTED_ZOOM;
|
||||
import static javafx.geometry.Pos.CENTER_LEFT;
|
||||
import static org.kordamp.ikonli.material2.Material2AL.ARROW_BACK;
|
||||
import static org.kordamp.ikonli.material2.Material2AL.ARROW_FORWARD;
|
||||
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.sampler.page.general.AccentColorSelector;
|
||||
import atlantafx.sampler.theme.ThemeManager;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.css.PseudoClass;
|
||||
import javafx.geometry.HorizontalDirection;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Separator;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2AL;
|
||||
|
||||
// This should really be refactored to more generic control someday.
|
||||
// - the whole component to PopoverMenu, that reuses JavaFX MenuItem API
|
||||
// - font size switcher to flat SpinnerMenuItem
|
||||
@SuppressWarnings("UnnecessaryLambda")
|
||||
public class QuickConfigMenu extends StackPane {
|
||||
|
||||
private static final PseudoClass SELECTED = PseudoClass.getPseudoClass("selected");
|
||||
private static final String EXIT_ID = "Exit";
|
||||
|
||||
private MainMenu mainMenu;
|
||||
private ThemeSelectionMenu themeSelectionMenu;
|
||||
private Runnable exitHandler;
|
||||
|
||||
private final Consumer<String> navHandler = s -> {
|
||||
Menu menu = null;
|
||||
switch (s) {
|
||||
case MainMenu.ID -> menu = getOrCreateMainMenu();
|
||||
case ThemeSelectionMenu.ID -> menu = getOrCreateThemeSelectionMenu();
|
||||
default -> {
|
||||
if (exitHandler != null) {
|
||||
exitHandler.run();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Objects.requireNonNull(menu);
|
||||
menu.update();
|
||||
getChildren().setAll(menu.getRoot());
|
||||
};
|
||||
|
||||
public void setExitHandler(Runnable exitHandler) {
|
||||
this.exitHandler = exitHandler;
|
||||
}
|
||||
|
||||
public QuickConfigMenu() {
|
||||
super();
|
||||
|
||||
getChildren().setAll(getOrCreateMainMenu());
|
||||
setId("quick-config-menu");
|
||||
}
|
||||
|
||||
private MainMenu getOrCreateMainMenu() {
|
||||
if (mainMenu == null) {
|
||||
mainMenu = new MainMenu(navHandler);
|
||||
}
|
||||
return mainMenu;
|
||||
}
|
||||
|
||||
private ThemeSelectionMenu getOrCreateThemeSelectionMenu() {
|
||||
if (themeSelectionMenu == null) {
|
||||
themeSelectionMenu = new ThemeSelectionMenu(navHandler);
|
||||
}
|
||||
return themeSelectionMenu;
|
||||
}
|
||||
|
||||
private static Pane menu(String title, HorizontalDirection direction) {
|
||||
var label = new Label(title);
|
||||
label.getStyleClass().add(TEXT_CAPTION);
|
||||
|
||||
var root = new HBox();
|
||||
root.setAlignment(CENTER_LEFT);
|
||||
root.getStyleClass().addAll("row", "action");
|
||||
|
||||
switch (direction) {
|
||||
case LEFT -> root.getChildren().setAll(new FontIcon(ARROW_BACK), new Spacer(), label, new Spacer());
|
||||
case RIGHT -> root.getChildren().setAll(label, new Spacer(), new FontIcon(ARROW_FORWARD));
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
public void update() {
|
||||
getOrCreateMainMenu().update();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private interface Menu {
|
||||
|
||||
void update();
|
||||
|
||||
Pane getRoot();
|
||||
}
|
||||
|
||||
private static class MainMenu extends VBox implements Menu {
|
||||
|
||||
private static final String ID = "MainMenu";
|
||||
|
||||
private final IntegerProperty zoom = new SimpleIntegerProperty(DEFAULT_ZOOM);
|
||||
private final BooleanBinding canZoomIn = Bindings.createBooleanBinding(
|
||||
() -> SUPPORTED_ZOOM.indexOf(zoom.get()) < SUPPORTED_ZOOM.size() - 1, zoom
|
||||
);
|
||||
private final BooleanBinding canZoomOut = Bindings.createBooleanBinding(
|
||||
() -> SUPPORTED_ZOOM.indexOf(zoom.get()) >= 1, zoom
|
||||
);
|
||||
|
||||
public MainMenu(Consumer<String> navHandler) {
|
||||
super();
|
||||
|
||||
Objects.requireNonNull(navHandler);
|
||||
|
||||
var themeSelectionMenu = menu("Theme", HorizontalDirection.RIGHT);
|
||||
themeSelectionMenu.setOnMouseClicked(e -> navHandler.accept(ThemeSelectionMenu.ID));
|
||||
|
||||
var accentSelector = new AccentColorSelector();
|
||||
accentSelector.setAlignment(Pos.CENTER);
|
||||
|
||||
// ~
|
||||
|
||||
var zoomInBtn = new Button("", new FontIcon(Feather.ZOOM_IN));
|
||||
zoomInBtn.getStyleClass().addAll(BUTTON_CIRCLE, BUTTON_ICON, FLAT);
|
||||
zoomInBtn.setOnAction(e -> {
|
||||
if (canZoomIn.get()) {
|
||||
zoom.set(SUPPORTED_ZOOM.get(SUPPORTED_ZOOM.indexOf(zoom.get()) + 1));
|
||||
}
|
||||
});
|
||||
zoomInBtn.disableProperty().bind(canZoomIn.not());
|
||||
|
||||
var zoomOutBtn = new Button("", new FontIcon(Feather.ZOOM_OUT));
|
||||
zoomOutBtn.getStyleClass().addAll(BUTTON_CIRCLE, BUTTON_ICON, FLAT);
|
||||
zoomOutBtn.setOnAction(e -> {
|
||||
if (canZoomOut.get()) {
|
||||
zoom.set(SUPPORTED_ZOOM.get(SUPPORTED_ZOOM.indexOf(zoom.get()) - 1));
|
||||
}
|
||||
});
|
||||
zoomOutBtn.disableProperty().bind(canZoomOut.not());
|
||||
|
||||
var zoomLabel = new Label();
|
||||
zoomLabel.textProperty().bind(Bindings.createStringBinding(() -> zoom.get() + "%", zoom));
|
||||
|
||||
var zoomBox = new HBox(zoomOutBtn, new Spacer(), zoomLabel, new Spacer(), zoomInBtn);
|
||||
zoomBox.setAlignment(CENTER_LEFT);
|
||||
zoomBox.getStyleClass().addAll("row");
|
||||
|
||||
final var tm = ThemeManager.getInstance();
|
||||
zoom.addListener((obs, old, val) -> {
|
||||
if (val != null && tm.getZoom() != val.intValue()) {
|
||||
tm.setZoom(val.intValue());
|
||||
}
|
||||
});
|
||||
|
||||
// ~
|
||||
|
||||
getChildren().setAll(
|
||||
themeSelectionMenu,
|
||||
new Separator(),
|
||||
accentSelector,
|
||||
new Separator(),
|
||||
zoomBox
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
zoom.set(ThemeManager.getInstance().getZoom());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pane getRoot() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ThemeSelectionMenu extends VBox implements Menu {
|
||||
|
||||
public static final String ID = "ThemeSelectionMenu";
|
||||
|
||||
private final List<Node> items = new ArrayList<>();
|
||||
|
||||
public ThemeSelectionMenu(Consumer<String> navHandler) {
|
||||
super();
|
||||
|
||||
Objects.requireNonNull(navHandler);
|
||||
var tm = ThemeManager.getInstance();
|
||||
|
||||
var mainMenu = menu("Theme", HorizontalDirection.LEFT);
|
||||
mainMenu.setOnMouseClicked(e -> navHandler.accept(MainMenu.ID));
|
||||
|
||||
getChildren().setAll(mainMenu, new Separator());
|
||||
|
||||
tm.getRepository().getAll().forEach(theme -> {
|
||||
var icon = new FontIcon(Material2AL.CHECK);
|
||||
|
||||
var item = new HBox(20, icon, new Label(theme.getName()));
|
||||
item.getStyleClass().addAll("row", "action", "radio");
|
||||
item.setUserData(theme.getName());
|
||||
item.setOnMouseClicked(e -> {
|
||||
tm.setTheme(theme);
|
||||
navHandler.accept(MainMenu.ID);
|
||||
navHandler.accept(QuickConfigMenu.EXIT_ID);
|
||||
});
|
||||
|
||||
items.add(item);
|
||||
getChildren().add(item);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
items.forEach(item -> item.pseudoClassStateChanged(
|
||||
SELECTED,
|
||||
Objects.equals(item.getUserData(), ThemeManager.getInstance().getTheme().getName())
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pane getRoot() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ import javafx.scene.layout.Priority;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
|
||||
public class Snippet {
|
||||
public final class Snippet {
|
||||
|
||||
private final Class<?> sourceClass;
|
||||
private final int id;
|
||||
|
@ -28,7 +28,7 @@ import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
|
||||
public class AccordionPage extends OutlinePage {
|
||||
public final class AccordionPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "Accordion";
|
||||
|
||||
@ -40,6 +40,7 @@ public class AccordionPage extends OutlinePage {
|
||||
public AccordionPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A user interface component that allows you to display a list of expandable \
|
||||
items and only one item can be open at a time. Each item in the [i]Accordion[/i] \
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.page.extras;
|
||||
package atlantafx.sampler.page.components;
|
||||
|
||||
import atlantafx.base.controls.Breadcrumbs;
|
||||
import atlantafx.base.controls.Breadcrumbs.BreadCrumbItem;
|
||||
@ -9,14 +9,16 @@ import atlantafx.base.util.BBCodeParser;
|
||||
import atlantafx.sampler.page.ExampleBox;
|
||||
import atlantafx.sampler.page.OutlinePage;
|
||||
import atlantafx.sampler.page.Snippet;
|
||||
import java.net.URI;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.HBox;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2AL;
|
||||
|
||||
public class BreadcrumbsPage extends OutlinePage {
|
||||
public final class BreadcrumbsPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "Breadcrumbs";
|
||||
|
||||
@ -25,9 +27,15 @@ public class BreadcrumbsPage extends OutlinePage {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable URI getJavadocUri() {
|
||||
return URI.create(String.format(AFX_JAVADOC_URI_TEMPLATE, "controls/" + getName()));
|
||||
}
|
||||
|
||||
public BreadcrumbsPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
Represents a bread crumb bar. This control is useful to visualize and navigate \
|
||||
a hierarchical path structure, such as file systems."""
|
@ -18,7 +18,7 @@ import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2AL;
|
||||
|
||||
public class ButtonPage extends OutlinePage {
|
||||
public final class ButtonPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "Button";
|
||||
|
||||
@ -30,6 +30,7 @@ public class ButtonPage extends OutlinePage {
|
||||
public ButtonPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A simple button control. The button control can contain text and/or a graphic.
|
||||
A button control has three different modes:
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.page.extras;
|
||||
package atlantafx.sampler.page.components;
|
||||
|
||||
import atlantafx.base.controls.InlineDatePicker;
|
||||
import atlantafx.base.theme.Styles;
|
||||
@ -9,6 +9,7 @@ import atlantafx.sampler.page.ExampleBox;
|
||||
import atlantafx.sampler.page.OutlinePage;
|
||||
import atlantafx.sampler.page.Snippet;
|
||||
import atlantafx.sampler.theme.CSSFragment;
|
||||
import java.net.URI;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
@ -22,7 +23,7 @@ import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.Duration;
|
||||
|
||||
public class CalendarPage extends OutlinePage {
|
||||
public final class CalendarPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "Calendar";
|
||||
private static final LocalDate TODAY = LocalDate.now(ZoneId.systemDefault());
|
||||
@ -32,9 +33,15 @@ public class CalendarPage extends OutlinePage {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getJavadocUri() {
|
||||
return URI.create(String.format(AFX_JAVADOC_URI_TEMPLATE, "controls/" + getName()));
|
||||
}
|
||||
|
||||
public CalendarPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
The date picker control that allows the user to select a date. Unlike standard JavaFX \
|
||||
[font=monospace]javafx.scene.control.DatePicker[/font] the [i]Calendar[/i] is not concealed \
|
@ -6,6 +6,7 @@ import atlantafx.base.util.BBCodeParser;
|
||||
import atlantafx.sampler.page.ExampleBox;
|
||||
import atlantafx.sampler.page.OutlinePage;
|
||||
import atlantafx.sampler.page.Snippet;
|
||||
import java.net.URI;
|
||||
import java.time.Month;
|
||||
import java.time.format.TextStyle;
|
||||
import java.util.Locale;
|
||||
@ -24,7 +25,7 @@ import javafx.scene.chart.StackedAreaChart;
|
||||
import javafx.scene.chart.StackedBarChart;
|
||||
import javafx.scene.chart.XYChart;
|
||||
|
||||
public class ChartPage extends OutlinePage {
|
||||
public final class ChartPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "Chart";
|
||||
|
||||
@ -33,10 +34,16 @@ public class ChartPage extends OutlinePage {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getJavadocUri() {
|
||||
return URI.create("https://openjfx.io/javadoc/20/javafx.controls/javafx/scene/chart/package-summary.html");
|
||||
}
|
||||
|
||||
public ChartPage() {
|
||||
super();
|
||||
|
||||
addPlainText("""
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
JavaFX provides a set of chart components specifically designed \
|
||||
for data visualization. The charts include common types such as \
|
||||
Bar, Line, Area, Pie, Scatter, and Bubble charts."""
|
||||
|
@ -10,7 +10,7 @@ import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.StackPane;
|
||||
|
||||
public class CheckBoxPage extends OutlinePage {
|
||||
public final class CheckBoxPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "CheckBox";
|
||||
|
||||
@ -25,6 +25,7 @@ public class CheckBoxPage extends OutlinePage {
|
||||
public CheckBoxPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A tri-state selection control is typically skinned as a box \
|
||||
with a checkmark or tick mark when checked."""
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
package atlantafx.sampler.page.components;
|
||||
|
||||
public class ChoiceBoxPage extends ComboBoxPage {
|
||||
public final class ChoiceBoxPage extends ComboBoxPage {
|
||||
|
||||
public static final String NAME = "ChoiceBox";
|
||||
|
||||
|
@ -11,7 +11,7 @@ import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.paint.Color;
|
||||
|
||||
public class ColorPickerPage extends OutlinePage {
|
||||
public final class ColorPickerPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "ColorPicker";
|
||||
|
||||
@ -23,6 +23,7 @@ public class ColorPickerPage extends OutlinePage {
|
||||
public ColorPickerPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
ColorPicker control allows the user to select a color from either \
|
||||
a standard palette of colors with a simple one click selection or \
|
||||
|
@ -33,6 +33,7 @@ public class ComboBoxPage extends OutlinePage {
|
||||
public ComboBoxPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A user interface component which shows a list of items out of which \
|
||||
user can select at most one item. JavaFX provides two pretty similar \
|
||||
|
@ -19,7 +19,7 @@ import org.kordamp.ikonli.Ikon;
|
||||
import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
public class ContextMenuPage extends AbstractPage {
|
||||
public final class ContextMenuPage extends AbstractPage {
|
||||
|
||||
public static final String NAME = "ContextMenu";
|
||||
|
||||
@ -31,6 +31,7 @@ public class ContextMenuPage extends AbstractPage {
|
||||
public ContextMenuPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A popup control containing a list of menu items. It allows for any [i]MenuItem[/i], \
|
||||
including its subclasses, to be inserted. A common use case for this class is \
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.page.extras;
|
||||
package atlantafx.sampler.page.components;
|
||||
|
||||
import atlantafx.base.controls.CustomTextField;
|
||||
import atlantafx.base.controls.MaskTextField;
|
||||
@ -10,6 +10,7 @@ import atlantafx.base.util.BBCodeParser;
|
||||
import atlantafx.sampler.page.ExampleBox;
|
||||
import atlantafx.sampler.page.OutlinePage;
|
||||
import atlantafx.sampler.page.Snippet;
|
||||
import java.net.URI;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
@ -19,12 +20,13 @@ import javafx.scene.Cursor;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2OutlinedAL;
|
||||
import org.kordamp.ikonli.material2.Material2OutlinedMZ;
|
||||
|
||||
public class CustomTextFieldPage extends OutlinePage {
|
||||
public final class CustomTextFieldPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "CustomTextField";
|
||||
|
||||
@ -33,9 +35,15 @@ public class CustomTextFieldPage extends OutlinePage {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getJavadocUri() {
|
||||
return URI.create(String.format(AFX_JAVADOC_URI_TEMPLATE, "controls/" + getName()));
|
||||
}
|
||||
|
||||
public CustomTextFieldPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A base class for placing nodes inside the text field itself, without being \
|
||||
on top of the users typed-in text."""
|
||||
@ -143,7 +151,6 @@ public class CustomTextFieldPage extends OutlinePage {
|
||||
timeField.textProperty().addListener((obs, old, val) -> {
|
||||
if (val != null) {
|
||||
try {
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
LocalTime.parse(val, timeFormatter);
|
||||
timeField.pseudoClassStateChanged(Styles.STATE_DANGER, false);
|
||||
} catch (DateTimeParseException e) {
|
@ -16,7 +16,7 @@ import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
public class DatePickerPage extends OutlinePage {
|
||||
public final class DatePickerPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "DatePicker";
|
||||
|
||||
@ -28,6 +28,7 @@ public class DatePickerPage extends OutlinePage {
|
||||
public DatePickerPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A date picker control that allows the user to enter a date as text or to select \
|
||||
a date from a calendar popup. The calendar is based on either the standard \
|
||||
|
@ -1,11 +1,12 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.page.extras;
|
||||
package atlantafx.sampler.page.components;
|
||||
|
||||
import atlantafx.base.layout.DeckPane;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import atlantafx.sampler.Resources;
|
||||
import atlantafx.sampler.page.AbstractPage;
|
||||
import java.net.URI;
|
||||
import java.util.function.Supplier;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
@ -23,7 +24,7 @@ import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2AL;
|
||||
import org.kordamp.ikonli.material2.Material2MZ;
|
||||
|
||||
public class DeckPanePage extends AbstractPage {
|
||||
public final class DeckPanePage extends AbstractPage {
|
||||
|
||||
public static final String NAME = "DeckPane";
|
||||
|
||||
@ -32,9 +33,15 @@ public class DeckPanePage extends AbstractPage {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getJavadocUri() {
|
||||
return URI.create(String.format(AFX_JAVADOC_URI_TEMPLATE, "layout/" + getName()));
|
||||
}
|
||||
|
||||
public DeckPanePage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
[i]DeckPane[/i] represents a pane that displays all of its child nodes in a deck, \
|
||||
where only one node can be visible at a time. It does not maintain any sequence \
|
||||
@ -43,7 +50,8 @@ public class DeckPanePage extends AbstractPage {
|
||||
|
||||
Using the control is as simple as calling the [code]swipeX(Node)[/code] and \
|
||||
[code]slideX(Node)[/code] methods, where [code]X[/code] represents the direction \
|
||||
of the transition that you want to achieve.""");
|
||||
of the transition that you want to achieve."""
|
||||
);
|
||||
addNode(createGallery());
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ import javafx.scene.layout.Priority;
|
||||
import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
public class DialogPage extends OutlinePage {
|
||||
public final class DialogPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "Dialog";
|
||||
|
||||
@ -37,6 +37,7 @@ public class DialogPage extends OutlinePage {
|
||||
public DialogPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
Dialog is a user interface component that allows to create dialog windows \
|
||||
that can be used to prompt users for information or to display messages or warnings."""
|
||||
|
@ -10,13 +10,14 @@ import atlantafx.sampler.event.ThemeEvent;
|
||||
import atlantafx.sampler.page.AbstractPage;
|
||||
import atlantafx.sampler.theme.HighlightJSTheme;
|
||||
import atlantafx.sampler.theme.ThemeManager;
|
||||
import java.net.URI;
|
||||
import javafx.css.PseudoClass;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.web.HTMLEditor;
|
||||
|
||||
public class HtmlEditorPage extends AbstractPage {
|
||||
public final class HtmlEditorPage extends AbstractPage {
|
||||
|
||||
private static final PseudoClass USE_LOCAL_URL = PseudoClass.getPseudoClass("use-local-url");
|
||||
|
||||
@ -27,11 +28,17 @@ public class HtmlEditorPage extends AbstractPage {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
private HTMLEditor editor = createHTMLEditor();
|
||||
@Override
|
||||
public URI getJavadocUri() {
|
||||
return URI.create("https://openjfx.io/javadoc/20/javafx.web/javafx/scene/web/HTMLEditor.html");
|
||||
}
|
||||
|
||||
private HTMLEditor editor = createHtmlEditor();
|
||||
|
||||
public HtmlEditorPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A control that allows for users to edit text, and apply styling to this text. \
|
||||
The underlying data model is HTML, although this is not shown visually to the end-user."""
|
||||
@ -67,7 +74,7 @@ public class HtmlEditorPage extends AbstractPage {
|
||||
fixToggle.selectedProperty().addListener((obs, old, val) -> {
|
||||
// toolbar icons can't be changed back without creating new editor instance #javafx-bug
|
||||
try {
|
||||
editor = createHTMLEditor();
|
||||
editor = createHtmlEditor();
|
||||
editor.pseudoClassStateChanged(USE_LOCAL_URL, val);
|
||||
content.getChildren().set(0, editor);
|
||||
editor.requestFocus();
|
||||
@ -80,7 +87,7 @@ public class HtmlEditorPage extends AbstractPage {
|
||||
return content;
|
||||
}
|
||||
|
||||
private HTMLEditor createHTMLEditor() {
|
||||
private HTMLEditor createHtmlEditor() {
|
||||
var editor = new HTMLEditor();
|
||||
editor.setPrefHeight(400);
|
||||
editor.setHtmlText(generateContent());
|
||||
|
@ -1,12 +1,13 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.page.extras;
|
||||
package atlantafx.sampler.page.components;
|
||||
|
||||
import atlantafx.base.theme.Styles;
|
||||
import atlantafx.base.util.BBCodeParser;
|
||||
import atlantafx.sampler.page.ExampleBox;
|
||||
import atlantafx.sampler.page.OutlinePage;
|
||||
import atlantafx.sampler.page.Snippet;
|
||||
import java.net.URI;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.CheckBox;
|
||||
@ -18,10 +19,11 @@ import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
public class InputGroupPage extends OutlinePage {
|
||||
public final class InputGroupPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "Input Group";
|
||||
|
||||
@ -30,14 +32,21 @@ public class InputGroupPage extends OutlinePage {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable URI getJavadocUri() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public InputGroupPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
You can use the following utility classes: [code]Styles.LEFT_PILL[/code], \
|
||||
[code]Styles.CENTER_PILL[/code], and [code]Styles.RIGHT_PILL[/code] to combine \
|
||||
various input controls into input groups that allow them to appear as a single \
|
||||
control. This is entirely a CSS feature and does not require any additional wrappers.""");
|
||||
control. This is entirely a CSS feature and does not require any additional wrappers."""
|
||||
);
|
||||
addSection("ComboBox", comboBoxExample());
|
||||
addSection("Button", buttonExample());
|
||||
addSection("Text Field", textFieldExample());
|
@ -1,79 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.page.components;
|
||||
|
||||
import atlantafx.base.theme.Styles;
|
||||
import atlantafx.base.util.BBCodeParser;
|
||||
import atlantafx.sampler.page.AbstractPage;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.FlowPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2AL;
|
||||
|
||||
public class LabelPage extends AbstractPage {
|
||||
|
||||
public static final String NAME = "Label";
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
public LabelPage() {
|
||||
super();
|
||||
|
||||
addFormattedText("""
|
||||
Label is a non-editable text control. A [i]Label[/i] is useful for displaying text that \
|
||||
is required to fit within a specific space, and thus may need to use an ellipsis \
|
||||
or truncation to size the string to fit."""
|
||||
);
|
||||
addNode(colorExample());
|
||||
}
|
||||
|
||||
private VBox colorExample() {
|
||||
var defaultLabel = new Label("default", createFontIcon());
|
||||
|
||||
var accentLabel = new Label("accent", createFontIcon());
|
||||
accentLabel.getStyleClass().add(Styles.ACCENT);
|
||||
|
||||
var successLabel = new Label("success", createFontIcon());
|
||||
successLabel.getStyleClass().add(Styles.SUCCESS);
|
||||
|
||||
var warningLabel = new Label("warning", createFontIcon());
|
||||
warningLabel.getStyleClass().add(Styles.WARNING);
|
||||
|
||||
var dangerLabel = new Label("danger", createFontIcon());
|
||||
dangerLabel.getStyleClass().add(Styles.DANGER);
|
||||
|
||||
var mutedLabel = new Label("muted", createFontIcon());
|
||||
mutedLabel.getStyleClass().add(Styles.TEXT_MUTED);
|
||||
|
||||
var subtleLabel = new Label("subtle", createFontIcon());
|
||||
subtleLabel.getStyleClass().add(Styles.TEXT_SUBTLE);
|
||||
|
||||
var description = BBCodeParser.createFormattedText("""
|
||||
You can use pseudo-classes to set the [i]Label[/i] color. Note that icon \
|
||||
inherits label color by default."""
|
||||
);
|
||||
|
||||
var labels = new FlowPane(
|
||||
20, 20,
|
||||
defaultLabel,
|
||||
accentLabel,
|
||||
successLabel,
|
||||
warningLabel,
|
||||
dangerLabel,
|
||||
mutedLabel,
|
||||
subtleLabel
|
||||
);
|
||||
|
||||
return new VBox(20, description, labels);
|
||||
}
|
||||
|
||||
private FontIcon createFontIcon(String... stylesClass) {
|
||||
var icon = new FontIcon(Material2AL.LABEL);
|
||||
icon.getStyleClass().addAll(stylesClass);
|
||||
return icon;
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ import javafx.util.StringConverter;
|
||||
import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
public class ListViewPage extends OutlinePage {
|
||||
public final class ListViewPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "ListView";
|
||||
|
||||
@ -49,10 +49,12 @@ public class ListViewPage extends OutlinePage {
|
||||
public ListViewPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A [i]ListView[/i] displays a horizontal or vertical list of items from which the \
|
||||
user may select, or with which the user may interact. A ListView is able to \
|
||||
have its generic type set to represent the type of data in the backing model.""");
|
||||
have its generic type set to represent the type of data in the backing model."""
|
||||
);
|
||||
addSection("Usage", usageExample());
|
||||
addSection("Row Style", rowStyleExample());
|
||||
addSection("Selection Color", selectionColorExample());
|
||||
|
@ -27,7 +27,7 @@ import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2OutlinedAL;
|
||||
|
||||
public class MenuBarPage extends AbstractPage {
|
||||
public final class MenuBarPage extends AbstractPage {
|
||||
|
||||
public static final String NAME = "MenuBar";
|
||||
|
||||
@ -39,6 +39,7 @@ public class MenuBarPage extends AbstractPage {
|
||||
public MenuBarPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A menu bar is a user interface component that typically appears at the top of \
|
||||
an application window or screen, and provides a series of drop-down menus that \
|
||||
|
@ -19,7 +19,7 @@ import javafx.scene.layout.HBox;
|
||||
import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
public class MenuButtonPage extends OutlinePage {
|
||||
public final class MenuButtonPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "MenuButton";
|
||||
|
||||
@ -31,6 +31,7 @@ public class MenuButtonPage extends OutlinePage {
|
||||
public MenuButtonPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
[i]MenuButton[/i] is a button which, when clicked or pressed, will \
|
||||
show a context (dropdown) menu.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.page.extras;
|
||||
package atlantafx.sampler.page.components;
|
||||
|
||||
import atlantafx.base.controls.ModalPane;
|
||||
import atlantafx.base.util.BBCodeParser;
|
||||
@ -23,7 +23,7 @@ import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
|
||||
public class ModalPanePage extends OutlinePage {
|
||||
public final class ModalPanePage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "ModalPane";
|
||||
|
||||
@ -50,10 +50,12 @@ public class ModalPanePage extends OutlinePage {
|
||||
}
|
||||
});
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A container for displaying application dialogs ot top of the current scene \
|
||||
without opening a modal {@link javafx.stage.Stage}. It's a translucent (glass) pane \
|
||||
that can hold arbitrary content as well as animate its appearance.""");
|
||||
without opening a modal [code]javafx.stage.Stage[/code]. It's a translucent \
|
||||
(glass) pane that can hold arbitrary content as well as animate its appearance."""
|
||||
);
|
||||
addSection("Usage", usageExample());
|
||||
addSection("Content Position", contentPositionExample());
|
||||
addSection("Persistent", persistentExample());
|
||||
@ -346,7 +348,10 @@ public class ModalPanePage extends OutlinePage {
|
||||
implement the famous JS lightbox effect."""
|
||||
);
|
||||
|
||||
return new ExampleBox(box, new Snippet(getClass(), 7), description);
|
||||
var example = new ExampleBox(box, new Snippet(getClass(), 7), description);
|
||||
example.setAllowDisable(false);
|
||||
|
||||
return example;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
@ -20,7 +20,7 @@ import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
public class PaginationPage extends OutlinePage {
|
||||
public final class PaginationPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "Pagination";
|
||||
|
||||
@ -32,6 +32,7 @@ public class PaginationPage extends OutlinePage {
|
||||
public PaginationPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A [i]Pagination[/i] control is used for navigation between pages of a single content, \
|
||||
which has been divided into smaller parts."""
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.page.extras;
|
||||
package atlantafx.sampler.page.components;
|
||||
|
||||
import atlantafx.base.controls.InlineDatePicker;
|
||||
import atlantafx.base.controls.Popover;
|
||||
@ -10,6 +10,7 @@ import atlantafx.sampler.page.ExampleBox;
|
||||
import atlantafx.sampler.page.OutlinePage;
|
||||
import atlantafx.sampler.page.Snippet;
|
||||
import atlantafx.sampler.theme.CSSFragment;
|
||||
import java.net.URI;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import javafx.geometry.Insets;
|
||||
@ -20,7 +21,7 @@ import javafx.scene.layout.HBox;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
|
||||
public class PopoverPage extends OutlinePage {
|
||||
public final class PopoverPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "Popover";
|
||||
|
||||
@ -29,15 +30,22 @@ public class PopoverPage extends OutlinePage {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getJavadocUri() {
|
||||
return URI.create(String.format(AFX_JAVADOC_URI_TEMPLATE, "controls/" + getName()));
|
||||
}
|
||||
|
||||
public PopoverPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
The [i]Popover[/i] is a control used to display additional information \
|
||||
or perform actions. It appears as a small popup window that overlays the \
|
||||
main interface, triggered by a user action such as a mouseover or tap. \
|
||||
It provides contextual information or options related to a specific object \
|
||||
or feature on the interface.""");
|
||||
or feature on the interface."""
|
||||
);
|
||||
addSection("Usage", usageExample());
|
||||
addSection("Position", positionExample());
|
||||
}
|
@ -33,7 +33,7 @@ import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
// #javafx-bug Indeterminate (animated) progress bar and also progress indicator
|
||||
// are very resource expensive. It consumes a single CPU core and a lot of memory.
|
||||
public class ProgressIndicatorPage extends OutlinePage {
|
||||
public final class ProgressIndicatorPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "ProgressIndicator";
|
||||
|
||||
@ -45,6 +45,7 @@ public class ProgressIndicatorPage extends OutlinePage {
|
||||
public ProgressIndicatorPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
JavaFX provides the two types of progress indicators: the [i]ProgressIndicator[/i] and \
|
||||
the [i]ProgressBar[/i]. In addition to them AtlantaFX also provides the \
|
||||
|
@ -10,7 +10,7 @@ import javafx.scene.control.RadioButton;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
public class RadioButtonPage extends OutlinePage {
|
||||
public final class RadioButtonPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "RadioButton";
|
||||
|
||||
@ -22,8 +22,10 @@ public class RadioButtonPage extends OutlinePage {
|
||||
public RadioButtonPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
[i]RadioButton[/i]'s create a series of items where only one item can be selected.""");
|
||||
[i]RadioButton[/i]'s create a series of items where only one item can be selected."""
|
||||
);
|
||||
addSection("Usage", usageExample());
|
||||
addSection("Toggle Group", toggleGroupExample());
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Region;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
public class ScrollPanePage extends AbstractPage {
|
||||
public final class ScrollPanePage extends AbstractPage {
|
||||
|
||||
public static final String NAME = "ScrollPane";
|
||||
|
||||
@ -22,6 +22,7 @@ public class ScrollPanePage extends AbstractPage {
|
||||
public ScrollPanePage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A control that provides a scrolled, clipped viewport of its contents. \
|
||||
It allows the user to scroll the content around either directly (panning) \
|
||||
|
@ -27,6 +27,7 @@ public final class SeparatorPage extends OutlinePage {
|
||||
public SeparatorPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A horizontal or vertical separator line. A horizontal separator occupies \
|
||||
the full horizontal space allocated to it (less padding), and a vertical \
|
||||
|
@ -11,7 +11,7 @@ import javafx.geometry.Orientation;
|
||||
import javafx.scene.control.Slider;
|
||||
import javafx.scene.layout.GridPane;
|
||||
|
||||
public class SliderPage extends OutlinePage {
|
||||
public final class SliderPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "Slider";
|
||||
|
||||
@ -23,6 +23,7 @@ public class SliderPage extends OutlinePage {
|
||||
public SliderPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
The [i]Slider[/i] control is used to display a continuous or discrete range of valid numeric \
|
||||
choices. It is typically represented visually as having a [i]track[/i] and a [i]knob[/i] \
|
||||
|
@ -24,7 +24,8 @@ public final class SpinnerPage extends OutlinePage {
|
||||
public SpinnerPage() {
|
||||
super();
|
||||
|
||||
addPlainText("""
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A single line text field that lets the user select a number or an object \
|
||||
value from an ordered sequence. The user may also be allowed to type a (legal) \
|
||||
value directly into the spinner."""
|
||||
|
@ -13,7 +13,7 @@ import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
public class SplitPanePage extends OutlinePage {
|
||||
public final class SplitPanePage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "SplitPane";
|
||||
|
||||
@ -25,6 +25,7 @@ public class SplitPanePage extends OutlinePage {
|
||||
public SplitPanePage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A control that has two or more sides, each separated by a divider, which can be \
|
||||
dragged by the user to give more space to one of the sides, resulting in the other \
|
||||
|
@ -33,7 +33,7 @@ import javafx.scene.layout.VBox;
|
||||
import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
public class TabPanePage extends OutlinePage {
|
||||
public final class TabPanePage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "TabPane";
|
||||
|
||||
@ -45,6 +45,7 @@ public class TabPanePage extends OutlinePage {
|
||||
public TabPanePage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
[i]TabPane[/i] is a control that provides a container for a group of tabs. By clicking \
|
||||
on a tab, the content of that tab becomes visible, while the content of the previously \
|
||||
|
@ -58,7 +58,7 @@ import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIconTableCell;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class TableViewPage extends OutlinePage {
|
||||
public final class TableViewPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "TableView";
|
||||
|
||||
@ -117,6 +117,7 @@ public class TableViewPage extends OutlinePage {
|
||||
public TableViewPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
The [i]TableView[/i] control is designed to visualize an unlimited number of rows of data, \
|
||||
broken out into columns."""
|
||||
|
@ -12,7 +12,7 @@ import java.util.stream.Stream;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
public class TextAreaPage extends OutlinePage {
|
||||
public final class TextAreaPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "TextArea";
|
||||
|
||||
@ -24,6 +24,7 @@ public class TextAreaPage extends OutlinePage {
|
||||
public TextAreaPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText(
|
||||
"Text input component that allows a user to enter multiple lines of plain text."
|
||||
);
|
||||
|
@ -12,7 +12,7 @@ import javafx.scene.control.PasswordField;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
public class TextFieldPage extends OutlinePage {
|
||||
public final class TextFieldPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "TextField";
|
||||
|
||||
@ -24,6 +24,7 @@ public class TextFieldPage extends OutlinePage {
|
||||
public TextFieldPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
Text input component that allows a user to enter a single line of unformatted text."""
|
||||
);
|
||||
|
@ -27,7 +27,7 @@ import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
|
||||
public class TitledPanePage extends OutlinePage {
|
||||
public final class TitledPanePage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "TitledPane";
|
||||
|
||||
@ -39,6 +39,7 @@ public class TitledPanePage extends OutlinePage {
|
||||
public TitledPanePage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
[i]TitledPane[/i] is a panel with a title that can be opened and closed. \
|
||||
It holds one or more user interface elements and you can expand and collapse it. \
|
||||
|
@ -16,7 +16,7 @@ import javafx.scene.layout.HBox;
|
||||
import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
public class ToggleButtonPage extends OutlinePage {
|
||||
public final class ToggleButtonPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "ToggleButton";
|
||||
|
||||
@ -28,6 +28,7 @@ public class ToggleButtonPage extends OutlinePage {
|
||||
public ToggleButtonPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A [i]ToggleButton[/i] is a special control having the ability to be selected."""
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.page.extras;
|
||||
package atlantafx.sampler.page.components;
|
||||
|
||||
import atlantafx.base.controls.ToggleSwitch;
|
||||
import atlantafx.base.theme.Styles;
|
||||
@ -8,11 +8,12 @@ import atlantafx.base.util.BBCodeParser;
|
||||
import atlantafx.sampler.page.ExampleBox;
|
||||
import atlantafx.sampler.page.OutlinePage;
|
||||
import atlantafx.sampler.page.Snippet;
|
||||
import java.net.URI;
|
||||
import javafx.geometry.HorizontalDirection;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
public class ToggleSwitchPage extends OutlinePage {
|
||||
public final class ToggleSwitchPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "ToggleSwitch";
|
||||
|
||||
@ -21,9 +22,15 @@ public class ToggleSwitchPage extends OutlinePage {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getJavadocUri() {
|
||||
return URI.create(String.format(AFX_JAVADOC_URI_TEMPLATE, "controls/" + getName()));
|
||||
}
|
||||
|
||||
public ToggleSwitchPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
The [i]ToggleSwitch[/i] is a control used to activate or deactivate a feature. \
|
||||
It consists of a horizontal bar with a small knob that can be moved to turn on \
|
@ -57,7 +57,7 @@ import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2OutlinedAL;
|
||||
import org.kordamp.ikonli.material2.Material2OutlinedMZ;
|
||||
|
||||
public class ToolBarPage extends OutlinePage {
|
||||
public final class ToolBarPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "ToolBar";
|
||||
|
||||
@ -69,6 +69,7 @@ public class ToolBarPage extends OutlinePage {
|
||||
public ToolBarPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
A [i]ToolBar[/i] is a control which displays items horizontally or vertically."""
|
||||
);
|
||||
|
@ -14,7 +14,7 @@ import javafx.scene.layout.HBox;
|
||||
import javafx.stage.PopupWindow.AnchorLocation;
|
||||
import javafx.util.Duration;
|
||||
|
||||
public class TooltipPage extends OutlinePage {
|
||||
public final class TooltipPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "Tooltip";
|
||||
|
||||
@ -26,13 +26,15 @@ public class TooltipPage extends OutlinePage {
|
||||
public TooltipPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
Tooltips are used for showing additional information when the node is hovered over by the mouse.
|
||||
|
||||
[ul]
|
||||
[li]Any node can show a tooltip.[/li]
|
||||
[li]A Tooltip is able to show within it an arbitrary scenegraph of nodes.[/li]
|
||||
[li]A single tooltip can be installed on multiple target nodes or multiple controls.[/li][/ul]""");
|
||||
[li]A single tooltip can be installed on multiple target nodes or multiple controls.[/li][/ul]"""
|
||||
);
|
||||
addSection("Usage", usageExample());
|
||||
addSection("Position", positionExample());
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.Callback;
|
||||
|
||||
public class TreeTableViewPage extends OutlinePage {
|
||||
public final class TreeTableViewPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "TreeTableView";
|
||||
|
||||
@ -57,10 +57,12 @@ public class TreeTableViewPage extends OutlinePage {
|
||||
public TreeTableViewPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
The [i]TreeTableView[/i] control is conceptually very similar to the \
|
||||
[i]TreeView[/i] and [i]TableView[/i] controls and basically supports the \
|
||||
same features. Please, see the corresponding pages for more examples.""");
|
||||
same features. Please, see the corresponding pages for more examples."""
|
||||
);
|
||||
addSection("Usage", usageExample());
|
||||
addSection("Playground", playground());
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ import javafx.util.StringConverter;
|
||||
import org.kordamp.ikonli.feather.Feather;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
public class TreeViewPage extends OutlinePage {
|
||||
public final class TreeViewPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "TreeView";
|
||||
|
||||
@ -49,6 +49,7 @@ public class TreeViewPage extends OutlinePage {
|
||||
public TreeViewPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
The [i]TreeView[/i] provides a way to present tree structures. A tree has \
|
||||
a root node which contains all the hierarchical values."""
|
||||
|
@ -15,7 +15,7 @@ import javafx.scene.layout.Region;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2AL;
|
||||
|
||||
public class AccentColorSelector extends HBox {
|
||||
final class AccentColorSelector extends HBox {
|
||||
|
||||
public AccentColorSelector() {
|
||||
super();
|
||||
|
@ -1,18 +1,20 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.page.extras;
|
||||
package atlantafx.sampler.page.general;
|
||||
|
||||
import atlantafx.base.theme.Styles;
|
||||
import atlantafx.base.util.BBCodeParser;
|
||||
import atlantafx.sampler.page.OutlinePage;
|
||||
import java.net.URI;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class BBCodePage extends OutlinePage {
|
||||
public final class BBCodePage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "BBCode Markup";
|
||||
|
||||
@ -21,15 +23,21 @@ public class BBCodePage extends OutlinePage {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable URI getJavadocUri() {
|
||||
return URI.create(String.format(AFX_JAVADOC_URI_TEMPLATE, "util/BBCodeParser"));
|
||||
}
|
||||
|
||||
public BBCodePage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
BBCode (Bulletin Board Code) is a lightweight markup language used to \
|
||||
format messages in many Internet forum software. The available tags of \
|
||||
BBCode are indicated by square brackets surrounding a keyword, and are \
|
||||
parsed before being translated into [s]HTML[/s] JavaFX layout :)""");
|
||||
|
||||
parsed before being translated into [s]HTML[/s] JavaFX layout :)"""
|
||||
);
|
||||
addSection("Text Type", textTypeReference());
|
||||
addSection("Text Style", textStyleReference());
|
||||
addSection("Subscript and Superscript", subscriptReference());
|
@ -14,7 +14,7 @@ import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.util.Duration;
|
||||
|
||||
class ColorPalette extends GridPane {
|
||||
final class ColorPalette extends GridPane {
|
||||
|
||||
private final List<ColorPaletteBlock> blocks = new ArrayList<>();
|
||||
private final ReadOnlyObjectWrapper<Color> bgBaseColor = new ReadOnlyObjectWrapper<>(Color.WHITE);
|
||||
|
@ -24,7 +24,7 @@ import javafx.scene.text.Text;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2AL;
|
||||
|
||||
class ColorPaletteBlock extends VBox {
|
||||
final class ColorPaletteBlock extends VBox {
|
||||
|
||||
private final String fgColorName;
|
||||
private final String bgColorName;
|
||||
|
@ -11,7 +11,7 @@ import javafx.scene.layout.FlowPane;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.util.Duration;
|
||||
|
||||
class ColorScale extends FlowPane {
|
||||
final class ColorScale extends FlowPane {
|
||||
|
||||
private final ReadOnlyObjectWrapper<Color> bgBaseColor = new ReadOnlyObjectWrapper<>(Color.WHITE);
|
||||
private final List<ColorScaleBlock> blocks = Arrays.asList(
|
||||
|
@ -12,7 +12,7 @@ import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.paint.Color;
|
||||
|
||||
class ColorScaleBlock extends VBox {
|
||||
final class ColorScaleBlock extends VBox {
|
||||
|
||||
private static final double BLOCK_WIDTH = 200;
|
||||
private static final double BLOCK_HEIGHT = 40;
|
||||
|
@ -43,7 +43,7 @@ import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2AL;
|
||||
|
||||
// Inspired by the https://colourcontrast.cc/
|
||||
class ContrastChecker extends GridPane {
|
||||
final class ContrastChecker extends GridPane {
|
||||
|
||||
public static final double CONTRAST_RATIO_THRESHOLD = 1.5;
|
||||
public static final double LUMINANCE_THRESHOLD = 0.55;
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
package atlantafx.sampler.page.general;
|
||||
|
||||
import atlantafx.sampler.page.OverlayDialog;
|
||||
import atlantafx.sampler.layout.OverlayDialog;
|
||||
import atlantafx.sampler.util.JColorUtils;
|
||||
import atlantafx.sampler.util.NodeUtils;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
|
@ -17,7 +17,7 @@ import javafx.scene.control.TableView;
|
||||
import org.kordamp.ikonli.Ikon;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
|
||||
public class IconBrowser extends TableView<List<Ikon>> {
|
||||
final class IconBrowser extends TableView<List<Ikon>> {
|
||||
|
||||
static final int FILTER_LEN = 2;
|
||||
|
||||
|
@ -9,6 +9,7 @@ import atlantafx.sampler.page.ExampleBox;
|
||||
import atlantafx.sampler.page.OutlinePage;
|
||||
import atlantafx.sampler.page.Snippet;
|
||||
import atlantafx.sampler.theme.CSSFragment;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import javafx.geometry.Pos;
|
||||
@ -16,6 +17,7 @@ import javafx.scene.Node;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.kordamp.ikonli.Ikon;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.javafx.StackedFontIcon;
|
||||
@ -23,7 +25,7 @@ import org.kordamp.ikonli.material2.Material2AL;
|
||||
import org.kordamp.ikonli.material2.Material2MZ;
|
||||
import org.kordamp.ikonli.material2.Material2OutlinedAL;
|
||||
|
||||
public class IconsPage extends OutlinePage {
|
||||
public final class IconsPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "Icons";
|
||||
|
||||
@ -32,12 +34,20 @@ public class IconsPage extends OutlinePage {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable URI getJavadocUri() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public IconsPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
AtlantaFX supports [url=https://kordamp.org/ikonli]Ikonli[/url] iconic fonts out \
|
||||
of the box, which can be used in conjunction with certain JavaFX components.""", true);
|
||||
of the box, which can be used in conjunction with certain JavaFX components.""",
|
||||
true
|
||||
);
|
||||
addSection("Color", colorExample());
|
||||
addSection("Stacking", stackingExample());
|
||||
addSection("Icon Pack", iconBrowser());
|
||||
|
@ -11,7 +11,7 @@ import atlantafx.base.theme.Styles;
|
||||
import atlantafx.sampler.Resources;
|
||||
import atlantafx.sampler.event.BrowseEvent;
|
||||
import atlantafx.sampler.event.DefaultEventBus;
|
||||
import atlantafx.sampler.page.OverlayDialog;
|
||||
import atlantafx.sampler.layout.OverlayDialog;
|
||||
import atlantafx.sampler.page.general.SceneBuilderDialogModel.Screen;
|
||||
import atlantafx.sampler.util.NodeUtils;
|
||||
import java.io.File;
|
||||
|
@ -20,7 +20,7 @@ import javafx.concurrent.Task;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class SceneBuilderDialogModel {
|
||||
final class SceneBuilderDialogModel {
|
||||
|
||||
public enum Screen {
|
||||
// order matters as it determines swipe direction when switching between screens
|
||||
|
@ -21,7 +21,7 @@ import java.util.Objects;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
class SceneBuilderInstaller {
|
||||
final class SceneBuilderInstaller {
|
||||
|
||||
private static final String THEME_PACK_FILE_NAME = "atlantafx-scene-builder.zip";
|
||||
|
||||
|
@ -13,7 +13,9 @@ import atlantafx.sampler.page.OutlinePage;
|
||||
import atlantafx.sampler.theme.SamplerTheme;
|
||||
import atlantafx.sampler.theme.ThemeManager;
|
||||
import atlantafx.sampler.util.Lazy;
|
||||
import java.net.URI;
|
||||
import java.util.Objects;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.geometry.HPos;
|
||||
@ -33,11 +35,12 @@ import javafx.scene.paint.Color;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.util.Duration;
|
||||
import javafx.util.StringConverter;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2OutlinedMZ;
|
||||
|
||||
@SuppressWarnings("UnnecessaryLambda")
|
||||
public class ThemePage extends OutlinePage {
|
||||
public final class ThemePage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "Theme";
|
||||
|
||||
@ -62,6 +65,11 @@ public class ThemePage extends OutlinePage {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable URI getJavadocUri() {
|
||||
return null;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private final Lazy<ThemeRepoManagerDialog> themeRepoManagerDialog;
|
||||
@ -131,12 +139,13 @@ public class ThemePage extends OutlinePage {
|
||||
}
|
||||
});
|
||||
|
||||
addSection("Theme", createThemeManagementSection());
|
||||
addPageHeader();
|
||||
addNode(createThemeManagementSection());
|
||||
addSection("Scene Builder", createSceneBuilderSection());
|
||||
addSection("Color Palette", createColorPaletteSection());
|
||||
addSection("Color Scale", createColorScaleSection());
|
||||
|
||||
selectCurrentTheme();
|
||||
Platform.runLater(this::selectCurrentTheme);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,7 +35,7 @@ import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2OutlinedAL;
|
||||
|
||||
@SuppressWarnings("UnnecessaryLambda")
|
||||
class ThemeRepoManager extends VBox {
|
||||
final class ThemeRepoManager extends VBox {
|
||||
|
||||
private static final Executor THREAD_POOL = Executors.newFixedThreadPool(3);
|
||||
private static final ThemeRepository REPO = ThemeManager.getInstance().getRepository();
|
||||
|
@ -3,7 +3,7 @@
|
||||
package atlantafx.sampler.page.general;
|
||||
|
||||
import atlantafx.base.theme.Styles;
|
||||
import atlantafx.sampler.page.OverlayDialog;
|
||||
import atlantafx.sampler.layout.OverlayDialog;
|
||||
import java.io.File;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
|
@ -11,6 +11,7 @@ import atlantafx.sampler.event.ThemeEvent;
|
||||
import atlantafx.sampler.page.ExampleBox;
|
||||
import atlantafx.sampler.page.OutlinePage;
|
||||
import atlantafx.sampler.page.Snippet;
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import javafx.geometry.Insets;
|
||||
@ -23,9 +24,11 @@ import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.util.Duration;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.kordamp.ikonli.javafx.FontIcon;
|
||||
import org.kordamp.ikonli.material2.Material2AL;
|
||||
|
||||
public class TypographyPage extends OutlinePage {
|
||||
public final class TypographyPage extends OutlinePage {
|
||||
|
||||
public static final String NAME = "Typography";
|
||||
|
||||
@ -36,24 +39,32 @@ public class TypographyPage extends OutlinePage {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable URI getJavadocUri() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public TypographyPage() {
|
||||
super();
|
||||
|
||||
addPageHeader();
|
||||
addFormattedText("""
|
||||
Because AtlantaFX is also distributed as a single CSS file, it does not come \
|
||||
with any fonts. However, it does support several utility classes demonstrated \
|
||||
below that can be used to manipulate font properties. If you need a formatted \
|
||||
text support have a look at [i]BBCodeParser[/i].""");
|
||||
text support have a look at [i]BBCodeParser[/i]."""
|
||||
);
|
||||
addSection("Font Size", fontSizeExample());
|
||||
addSection("Font Weight", fontWeightExample());
|
||||
addSection("Font Style", fontStyleExample());
|
||||
addSection("Text Color", textColorExample());
|
||||
addSection("Label", labelExample());
|
||||
addSection("Hyperlink", hyperlinkExample());
|
||||
|
||||
DefaultEventBus.getInstance().subscribe(ThemeEvent.class, e -> {
|
||||
var eventType = e.getEventType();
|
||||
if (eventType == EventType.THEME_CHANGE || eventType == EventType.FONT_CHANGE) {
|
||||
updateFontInfo(Duration.seconds(1));
|
||||
updateFontInfo();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -62,10 +73,10 @@ public class TypographyPage extends OutlinePage {
|
||||
protected void onRendered() {
|
||||
super.onRendered();
|
||||
// font metrics can only be obtained by requesting from a rendered node
|
||||
updateFontInfo(Duration.seconds(1));
|
||||
updateFontInfo();
|
||||
}
|
||||
|
||||
private void updateFontInfo(Duration delay) {
|
||||
private void updateFontInfo() {
|
||||
if (fontSizeGridPane == null) {
|
||||
return;
|
||||
}
|
||||
@ -309,7 +320,62 @@ public class TypographyPage extends OutlinePage {
|
||||
);
|
||||
box.setAlignment(Pos.BASELINE_LEFT);
|
||||
|
||||
var example = new ExampleBox(box, new Snippet(getClass(), 5));
|
||||
var description = BBCodeParser.createFormattedText("""
|
||||
An HTML like label which can be a graphic and/or text which responds to \
|
||||
rollovers and clicks. When a hyperlink is clicked/pressed [code]#isVisited[/code] \
|
||||
becomes "true". A Hyperlink behaves just like a [i]Button[/i]."""
|
||||
);
|
||||
|
||||
var example = new ExampleBox(box, new Snippet(getClass(), 5), description);
|
||||
example.setAllowDisable(false);
|
||||
|
||||
return example;
|
||||
}
|
||||
|
||||
private ExampleBox labelExample() {
|
||||
//snippet_6:start
|
||||
var defaultLabel = new Label("default", createFontIcon());
|
||||
|
||||
var accentLabel = new Label("accent", createFontIcon());
|
||||
accentLabel.getStyleClass().add(Styles.ACCENT);
|
||||
|
||||
var successLabel = new Label("success", createFontIcon());
|
||||
successLabel.getStyleClass().add(Styles.SUCCESS);
|
||||
|
||||
var warningLabel = new Label("warning", createFontIcon());
|
||||
warningLabel.getStyleClass().add(Styles.WARNING);
|
||||
|
||||
var dangerLabel = new Label("danger", createFontIcon());
|
||||
dangerLabel.getStyleClass().add(Styles.DANGER);
|
||||
|
||||
var mutedLabel = new Label("muted", createFontIcon());
|
||||
mutedLabel.getStyleClass().add(Styles.TEXT_MUTED);
|
||||
|
||||
var subtleLabel = new Label("subtle", createFontIcon());
|
||||
subtleLabel.getStyleClass().add(Styles.TEXT_SUBTLE);
|
||||
//snippet_6:end
|
||||
|
||||
var box = new FlowPane(
|
||||
20, 20,
|
||||
defaultLabel,
|
||||
accentLabel,
|
||||
successLabel,
|
||||
warningLabel,
|
||||
dangerLabel,
|
||||
mutedLabel,
|
||||
subtleLabel
|
||||
);
|
||||
|
||||
var description = BBCodeParser.createFormattedText("""
|
||||
Label is a non-editable text control. A [i]Label[/i] is useful for displaying text \
|
||||
that is required to fit within a specific space, and thus may need to use an ellipsis \
|
||||
or truncation to size the string to fit.
|
||||
|
||||
You can use pseudo-classes to set the [i]Label[/i] color. Note that icon \
|
||||
inherits label color by default."""
|
||||
);
|
||||
|
||||
var example = new ExampleBox(box, new Snippet(getClass(), 6), description);
|
||||
example.setAllowDisable(false);
|
||||
|
||||
return example;
|
||||
@ -321,4 +387,10 @@ public class TypographyPage extends OutlinePage {
|
||||
label.setStyle("-fx-font-family:monospace;");
|
||||
return label;
|
||||
}
|
||||
|
||||
private FontIcon createFontIcon(String... stylesClass) {
|
||||
var icon = new FontIcon(Material2AL.LABEL);
|
||||
icon.getStyleClass().addAll(stylesClass);
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
package atlantafx.sampler.page.general;
|
||||
package atlantafx.sampler.page.showcase;
|
||||
|
||||
import static atlantafx.sampler.util.Containers.setScrollConstraints;
|
||||
import static javafx.scene.control.ScrollPane.ScrollBarPolicy.AS_NEEDED;
|
||||
@ -8,6 +8,7 @@ import static javafx.scene.control.ScrollPane.ScrollBarPolicy.AS_NEEDED;
|
||||
import atlantafx.sampler.Resources;
|
||||
import atlantafx.sampler.page.Page;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Parent;
|
||||
@ -15,8 +16,9 @@ import javafx.scene.control.ScrollPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class OverviewPage extends ScrollPane implements Page {
|
||||
public final class OverviewPage extends ScrollPane implements Page {
|
||||
|
||||
public static final String NAME = "Overview";
|
||||
|
||||
@ -65,6 +67,11 @@ public class OverviewPage extends ScrollPane implements Page {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable URI getJavadocUri() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
}
|
@ -3,6 +3,7 @@ package atlantafx.sampler.page.showcase;
|
||||
import atlantafx.base.controls.Spacer;
|
||||
import atlantafx.base.theme.Styles;
|
||||
import atlantafx.sampler.page.Page;
|
||||
import java.net.URI;
|
||||
import java.util.Objects;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
@ -105,6 +106,11 @@ public abstract class ShowcasePage extends StackPane implements Page {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable URI getJavadocUri() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ public final class SamplerTheme implements Theme {
|
||||
|
||||
private static final int PARSE_LIMIT = 250;
|
||||
private static final Pattern COLOR_PATTERN =
|
||||
Pattern.compile("\s*?(-color-(fg|bg|accent|success|danger)-.+?):\s*?(.+?);");
|
||||
Pattern.compile("\s*?(-color-(fg|bg|accent|success|danger|warning)-.+?):\s*?(.+?);");
|
||||
|
||||
private final Theme theme;
|
||||
|
||||
|
@ -9,6 +9,7 @@ import javafx.animation.Timeline;
|
||||
import javafx.scene.Node;
|
||||
import javafx.util.Duration;
|
||||
|
||||
@Deprecated
|
||||
public final class Animations {
|
||||
|
||||
public static final Interpolator EASE = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
|
||||
|
@ -13,6 +13,7 @@ import javafx.scene.layout.ColumnConstraints;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.Region;
|
||||
|
||||
@Deprecated
|
||||
public final class Containers {
|
||||
|
||||
public static final ColumnConstraints H_GROW_NEVER = columnConstraints(Priority.NEVER);
|
||||
|
@ -27,7 +27,6 @@ module atlantafx.sampler {
|
||||
exports atlantafx.sampler.page;
|
||||
exports atlantafx.sampler.page.general;
|
||||
exports atlantafx.sampler.page.components;
|
||||
exports atlantafx.sampler.page.extras;
|
||||
exports atlantafx.sampler.page.showcase;
|
||||
exports atlantafx.sampler.theme;
|
||||
exports atlantafx.sampler.util;
|
||||
@ -41,4 +40,5 @@ module atlantafx.sampler {
|
||||
opens atlantafx.sampler.images;
|
||||
opens atlantafx.sampler.images.modena;
|
||||
opens atlantafx.sampler.page.general;
|
||||
opens atlantafx.sampler.page.showcase;
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@use "fonts";
|
||||
@use "root";
|
||||
@use "scene-builder-wizard";
|
||||
@use "util";
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@use "general";
|
||||
@use "layout";
|
||||
@use "widgets";
|
||||
@use "components"
|
||||
@use "page";
|
||||
@use "theme";
|
||||
@use "util"
|
||||
|
@ -1,5 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@use "fonts";
|
||||
@use "root";
|
||||
@use "main";
|
||||
@use "sidebar";
|
||||
@use "overlay";
|
||||
@use "page";
|
||||
|
@ -1,12 +1,4 @@
|
||||
@mixin link-button() {
|
||||
-fx-icon-color: -color-fg-emphasis;
|
||||
-fx-fill: -color-fg-emphasis;
|
||||
-fx-icon-size: 20px;
|
||||
|
||||
&:hover {
|
||||
-fx-effect: dropshadow(gaussian, -color-fg-emphasis, 20, 0.1, 0, 0)
|
||||
}
|
||||
}
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#main {
|
||||
.source-code {
|
||||
@ -25,153 +17,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#header-bar {
|
||||
-fx-background-color: -color-accent-emphasis;
|
||||
-fx-padding: 0px 20px 0px 0;
|
||||
-fx-spacing: 30px;
|
||||
|
||||
>.logo {
|
||||
-fx-padding: 0px 0 0px 10px;
|
||||
|
||||
>.image {
|
||||
-fx-background-color:-color-success-emphasis;
|
||||
-fx-background-radius: 6px;
|
||||
}
|
||||
|
||||
>.label {
|
||||
-fx-text-fill: -color-fg-emphasis;
|
||||
}
|
||||
|
||||
>.version {
|
||||
-fx-padding: -1em 0 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
>.text-field {
|
||||
-fx-background-insets: 0;
|
||||
-fx-padding: 0;
|
||||
-fx-opacity: 0.85;
|
||||
|
||||
-color-input-bg: -color-accent-emphasis;
|
||||
-color-input-bg-focused: -color-accent-emphasis;
|
||||
-color-input-fg: -color-fg-emphasis;
|
||||
-color-input-border: -color-fg-emphasis;
|
||||
-color-input-border-focused: -color-fg-emphasis;
|
||||
-fx-prompt-text-fill: -color-fg-emphasis;
|
||||
|
||||
.ikonli-font-icon {
|
||||
-fx-icon-color: -color-fg-emphasis;
|
||||
-fx-fill: -color-fg-emphasis;
|
||||
}
|
||||
}
|
||||
|
||||
>.search-button {
|
||||
-color-button-bg: -color-accent-emphasis;
|
||||
-color-button-fg: -color-fg-emphasis;
|
||||
-color-button-border: transparent;
|
||||
-color-button-bg-hover: -color-accent-6;
|
||||
-color-button-fg-hover: -color-fg-emphasis;
|
||||
-color-button-border-hover: transparent;
|
||||
-color-button-bg-focused: -color-accent-emphasis;
|
||||
-color-button-fg-focused: -color-fg-emphasis;
|
||||
-color-button-border-focused: transparent;
|
||||
-color-button-bg-pressed: -color-accent-emphasis;
|
||||
-color-button-fg-pressed: -color-fg-emphasis;
|
||||
-color-button-border-pressed: transparent;
|
||||
-color-button-shadow: transparent;
|
||||
|
||||
-fx-padding: 6px 16px 6px 12px;
|
||||
|
||||
>.box {
|
||||
>* {
|
||||
-fx-fill: -color-fg-emphasis;
|
||||
}
|
||||
|
||||
>.label {
|
||||
-fx-text-fill: -color-fg-emphasis;
|
||||
-fx-border-color: -color-fg-emphasis;
|
||||
-fx-border-width: 1;
|
||||
-fx-padding: 2px 6px 2px 6px;
|
||||
-fx-opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
>.page-title {
|
||||
-fx-text-fill: -color-fg-emphasis;
|
||||
-fx-padding: 0 0 0 30px;
|
||||
}
|
||||
|
||||
>.ikonli-font-icon {
|
||||
@include link-button();
|
||||
}
|
||||
|
||||
>.dev-mode-indicator {
|
||||
-fx-background-color: -color-warning-emphasis;
|
||||
-fx-text-fill: -color-fg-emphasis;
|
||||
-fx-background-radius: 10px;
|
||||
-fx-padding: 5px 10px 5px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
|
||||
.nav-tree-cell {
|
||||
-fx-padding: 0;
|
||||
-fx-indent: 8px;
|
||||
-color-cell-bg: -color-bg-inset;
|
||||
-color-cell-bg-selected: -color-bg-inset;
|
||||
-color-cell-bg-selected-focused: -color-bg-inset;
|
||||
-fx-background-radius: 5px;
|
||||
|
||||
>.tree-disclosure-node,
|
||||
>.tree-disclosure-node>.arrow {
|
||||
-fx-min-width: 0;
|
||||
-fx-pref-width: 0;
|
||||
-fx-max-width: 0;
|
||||
-fx-min-height: 0;
|
||||
-fx-pref-height: 0;
|
||||
-fx-max-height: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
>.container {
|
||||
-fx-min-height: 2.1em;
|
||||
-fx-pref-height: 2.1em;
|
||||
-fx-max-height: 2.1em;
|
||||
-fx-padding: 0 0 0 8px;
|
||||
}
|
||||
|
||||
&:selected >.container >.title {
|
||||
-fx-font-weight: bold;
|
||||
-fx-text-fill: -color-accent-fg;
|
||||
}
|
||||
|
||||
&:hover:filled {
|
||||
-color-cell-bg: -color-accent-subtle;
|
||||
}
|
||||
|
||||
&:group {
|
||||
>.container {
|
||||
-fx-min-height: 2.5em;
|
||||
-fx-pref-height: 2.5em;
|
||||
-fx-max-height: 2.5em;
|
||||
-fx-padding: 0 0 0 8px;
|
||||
|
||||
.ikonli-font-icon {
|
||||
-fx-fill: -color-accent-fg;
|
||||
-fx-icon-color: -color-accent-fg;
|
||||
}
|
||||
|
||||
>.arrow {
|
||||
-fx-icon-code: mdal-expand_more;
|
||||
}
|
||||
}
|
||||
|
||||
&:expanded>.container>.arrow {
|
||||
-fx-icon-code: mdal-chevron_right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@use "accent-colors" as ac;
|
||||
@use "../theme/accent-colors" as ac;
|
||||
|
||||
@mixin hide() {
|
||||
-fx-min-width: 0;
|
110
sampler/src/main/resources/atlantafx/sampler/assets/styles/scss/layout/_sidebar.scss
Normal file
110
sampler/src/main/resources/atlantafx/sampler/assets/styles/scss/layout/_sidebar.scss
Normal file
@ -0,0 +1,110 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#sidebar {
|
||||
-fx-background-color: -color-bg-inset;
|
||||
-fx-border-color: -color-border-default;
|
||||
-fx-border-width: 0 1px 0 0;
|
||||
|
||||
>.header {
|
||||
-fx-padding: 20px 10px 20px 10px;
|
||||
-fx-spacing: 20px;
|
||||
|
||||
>.logo {
|
||||
.label {
|
||||
-fx-text-fill: -color-fg-muted;
|
||||
}
|
||||
|
||||
>.palette {
|
||||
>.ikonli-font-icon {
|
||||
-fx-fill: -color-fg-muted;
|
||||
-fx-icon-color: -color-fg-muted;
|
||||
}
|
||||
}
|
||||
|
||||
.dev-indicator {
|
||||
-fx-padding: -0.75em 0 0 0;
|
||||
-fx-font-size: 12px;
|
||||
-fx-font-weight: normal;
|
||||
-fx-cursor: hand;
|
||||
}
|
||||
}
|
||||
|
||||
>.search-button {
|
||||
-color-button-bg: -color-bg-default;
|
||||
-color-button-border: -color-border-default;
|
||||
-color-button-border-hover: -color-border-default;
|
||||
-color-button-border-focused: -color-border-default;
|
||||
-color-button-border-pressed: -color-border-default;
|
||||
-color-button-shadow: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
>.footer {
|
||||
-fx-padding: 4px 10px 4px 10px;
|
||||
-fx-alignment: CENTER;
|
||||
}
|
||||
|
||||
.nav-tree-cell {
|
||||
-fx-padding: 0;
|
||||
-fx-indent: 0;
|
||||
-color-cell-bg: -color-bg-inset;
|
||||
-color-cell-bg-selected: -color-accent-subtle;
|
||||
-color-cell-bg-selected-focused: -color-accent-subtle;
|
||||
-color-cell-border: -color-bg-inset;
|
||||
-fx-background-radius: 5px;
|
||||
|
||||
>.tree-disclosure-node,
|
||||
>.tree-disclosure-node>.arrow {
|
||||
-fx-min-width: 0;
|
||||
-fx-pref-width: 0;
|
||||
-fx-max-width: 0;
|
||||
-fx-min-height: 0;
|
||||
-fx-pref-height: 0;
|
||||
-fx-max-height: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
>.container {
|
||||
-fx-min-height: 2.1em;
|
||||
-fx-pref-height: 2.1em;
|
||||
-fx-max-height: 2.1em;
|
||||
-fx-padding: 0 0 0 1.2em;
|
||||
|
||||
-fx-border-color: -color-border-muted;
|
||||
-fx-border-width: 0 0 0 1;
|
||||
}
|
||||
|
||||
&:selected>.container>.title {
|
||||
-fx-font-weight: bold;
|
||||
-fx-text-fill: -color-accent-fg;
|
||||
}
|
||||
|
||||
&:hover:filled {
|
||||
-color-cell-bg: -color-accent-subtle;
|
||||
-color-cell-bg-selected: -color-accent-subtle;
|
||||
-color-cell-bg-selected-focused: -color-accent-subtle;
|
||||
}
|
||||
|
||||
&:group {
|
||||
>.container {
|
||||
-fx-min-height: 2.5em;
|
||||
-fx-pref-height: 2.5em;
|
||||
-fx-max-height: 2.5em;
|
||||
-fx-padding: 0 0 0 8px;
|
||||
|
||||
.ikonli-font-icon {
|
||||
-fx-fill: -color-fg-muted;
|
||||
-fx-icon-color: -color-fg-muted;
|
||||
}
|
||||
|
||||
>.arrow {
|
||||
-fx-icon-code: mdal-add;
|
||||
}
|
||||
}
|
||||
|
||||
&:expanded>.container>.arrow {
|
||||
-fx-icon-code: mdmz-remove;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@use "layout";
|
||||
@use "html-editor-fix";
|
||||
@use "icon-browser";
|
||||
@use "showcase";
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user