Make small improvements to Sampler

- Support internal links
- Hide disable switch in some examples
This commit is contained in:
mkpaz 2023-05-26 21:43:42 +04:00
parent 39cf7bd992
commit cf2f46a4e0
15 changed files with 188 additions and 38 deletions

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: MIT */
package atlantafx.sampler.event;
import atlantafx.sampler.page.Page;
public final class NavEvent extends Event {
private final Class<? extends Page> page;
public NavEvent(Class<? extends Page> page) {
this.page = page;
}
public Class<? extends Page> getPage() {
return page;
}
@Override
public String toString() {
return "NavEvent{"
+ "page=" + page
+ "} " + super.toString();
}
}

@ -5,6 +5,8 @@ package atlantafx.sampler.layout;
import static atlantafx.sampler.layout.MainModel.SubLayer.PAGE; import static atlantafx.sampler.layout.MainModel.SubLayer.PAGE;
import static atlantafx.sampler.layout.MainModel.SubLayer.SOURCE_CODE; import static atlantafx.sampler.layout.MainModel.SubLayer.SOURCE_CODE;
import atlantafx.sampler.event.DefaultEventBus;
import atlantafx.sampler.event.NavEvent;
import atlantafx.sampler.page.Page; import atlantafx.sampler.page.Page;
import atlantafx.sampler.page.components.AccordionPage; import atlantafx.sampler.page.components.AccordionPage;
import atlantafx.sampler.page.components.AnimationsPage; import atlantafx.sampler.page.components.AnimationsPage;
@ -94,6 +96,10 @@ public class MainModel {
.toList(); .toList();
} }
public MainModel() {
DefaultEventBus.getInstance().subscribe(NavEvent.class, e -> navigate(e.getPage()));
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Properties // // Properties //
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////

@ -3,19 +3,47 @@
package atlantafx.sampler.layout; package atlantafx.sampler.layout;
import atlantafx.sampler.page.Page; import atlantafx.sampler.page.Page;
import atlantafx.sampler.page.components.BreadcrumbsPage;
import atlantafx.sampler.page.components.CalendarPage;
import atlantafx.sampler.page.components.CardPage;
import atlantafx.sampler.page.components.CustomTextFieldPage;
import atlantafx.sampler.page.components.DeckPanePage;
import atlantafx.sampler.page.components.InputGroupPage;
import atlantafx.sampler.page.components.MessagePage;
import atlantafx.sampler.page.components.ModalPanePage;
import atlantafx.sampler.page.components.PopoverPage;
import atlantafx.sampler.page.components.TilePage;
import atlantafx.sampler.page.components.ToggleSwitchPage;
import atlantafx.sampler.page.general.BBCodePage;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import javafx.scene.Node; import javafx.scene.Node;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
record Nav(String title, record Nav(String title,
@Nullable Node graphic, @Nullable Node graphic,
@Nullable Class<? extends Page> pageClass, @Nullable Class<? extends Page> pageClass,
@Nullable List<String> searchKeywords) { @Nullable List<String> searchKeywords) {
public static final Nav ROOT = new Nav("ROOT", null, null, null); public static final Nav ROOT = new Nav("ROOT", null, null, null);
private static final Set<Class<? extends Page>> TAGGED_PAGES = Set.of(
BBCodePage.class,
BreadcrumbsPage.class,
CalendarPage.class,
CardPage.class,
CustomTextFieldPage.class,
DeckPanePage.class,
InputGroupPage.class,
MessagePage.class,
ModalPanePage.class,
PopoverPage.class,
TilePage.class,
ToggleSwitchPage.class
);
public Nav { public Nav {
Objects.requireNonNull(title, "title"); Objects.requireNonNull(title, "title");
searchKeywords = Objects.requireNonNullElse(searchKeywords, Collections.emptyList()); searchKeywords = Objects.requireNonNullElse(searchKeywords, Collections.emptyList());
@ -31,6 +59,10 @@ record Nav(String title,
|| (searchKeywords != null && searchKeywords.stream().anyMatch(keyword -> contains(keyword, filter))); || (searchKeywords != null && searchKeywords.stream().anyMatch(keyword -> contains(keyword, filter)));
} }
public boolean isTagged() {
return pageClass != null && TAGGED_PAGES.contains(pageClass);
}
private boolean contains(String text, String filter) { private boolean contains(String text, String filter) {
return text.toLowerCase().contains(filter.toLowerCase()); return text.toLowerCase().contains(filter.toLowerCase());
} }

@ -5,6 +5,7 @@ package atlantafx.sampler.layout;
import atlantafx.base.controls.Spacer; import atlantafx.base.controls.Spacer;
import atlantafx.base.theme.Tweaks; import atlantafx.base.theme.Tweaks;
import atlantafx.sampler.page.Page; import atlantafx.sampler.page.Page;
import atlantafx.sampler.util.NodeUtils;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
@ -12,6 +13,7 @@ import javafx.css.PseudoClass;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.scene.Cursor; import javafx.scene.Cursor;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.TreeCell; import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem; import javafx.scene.control.TreeItem;
@ -51,6 +53,7 @@ public final class NavTree extends TreeView<Nav> {
private final HBox root; private final HBox root;
private final Label titleLabel; private final Label titleLabel;
private final Node arrowIcon; private final Node arrowIcon;
private final Label tagLabel;
public NavTreeCell() { public NavTreeCell() {
super(); super();
@ -62,9 +65,12 @@ public final class NavTree extends TreeView<Nav> {
arrowIcon = new FontIcon(); arrowIcon = new FontIcon();
arrowIcon.getStyleClass().add("arrow"); arrowIcon.getStyleClass().add("arrow");
tagLabel = new Label("new");
tagLabel.getStyleClass().add("tag");
root = new HBox(); root = new HBox();
root.setAlignment(Pos.CENTER_LEFT); root.setAlignment(Pos.CENTER_LEFT);
root.getChildren().setAll(titleLabel, new Spacer(), arrowIcon); root.getChildren().setAll(titleLabel, new Spacer(), arrowIcon, tagLabel);
root.setCursor(Cursor.HAND); root.setCursor(Cursor.HAND);
root.getStyleClass().add("container"); root.getStyleClass().add("container");
root.setMaxWidth(ApplicationWindow.SIDEBAR_WIDTH - 10); root.setMaxWidth(ApplicationWindow.SIDEBAR_WIDTH - 10);
@ -99,7 +105,8 @@ public final class NavTree extends TreeView<Nav> {
titleLabel.setGraphic(nav.graphic()); titleLabel.setGraphic(nav.graphic());
pseudoClassStateChanged(GROUP, nav.isGroup()); pseudoClassStateChanged(GROUP, nav.isGroup());
arrowIcon.setVisible(nav.isGroup()); NodeUtils.toggleVisibility(arrowIcon, nav.isGroup());
NodeUtils.toggleVisibility(tagLabel, nav.isTagged());
} }
} }
} }

@ -9,6 +9,7 @@ import atlantafx.base.theme.Tweaks;
import atlantafx.base.util.BBCodeParser; import atlantafx.base.util.BBCodeParser;
import atlantafx.sampler.event.BrowseEvent; import atlantafx.sampler.event.BrowseEvent;
import atlantafx.sampler.event.DefaultEventBus; import atlantafx.sampler.event.DefaultEventBus;
import atlantafx.sampler.event.NavEvent;
import atlantafx.sampler.event.PageEvent; import atlantafx.sampler.event.PageEvent;
import atlantafx.sampler.layout.ApplicationWindow; import atlantafx.sampler.layout.ApplicationWindow;
import java.net.URI; import java.net.URI;
@ -27,7 +28,6 @@ import javafx.scene.control.MenuItem;
import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination; import javafx.scene.input.KeyCodeCombination;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import net.datafaker.Faker; import net.datafaker.Faker;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.kordamp.ikonli.feather.Feather; import org.kordamp.ikonli.feather.Feather;
@ -71,15 +71,30 @@ public interface Page {
return Feather.values()[RANDOM.nextInt(Feather.values().length)]; return Feather.values()[RANDOM.nextInt(Feather.values().length)];
} }
@SuppressWarnings("unchecked")
default Node createFormattedText(String text, boolean handleUrl) { default Node createFormattedText(String text, boolean handleUrl) {
var node = BBCodeParser.createFormattedText(text); var node = BBCodeParser.createFormattedText(text);
if (handleUrl) { if (handleUrl) {
node.addEventFilter(ActionEvent.ACTION, e -> { node.addEventFilter(ActionEvent.ACTION, e -> {
if (e.getTarget() instanceof Hyperlink link && link.getUserData() != null) { if (e.getTarget() instanceof Hyperlink link && link.getUserData() instanceof String url) {
DefaultEventBus.getInstance().publish( if (url.startsWith("https://") || url.startsWith("http://")) {
new BrowseEvent(URI.create((String) link.getUserData())) DefaultEventBus.getInstance().publish(new BrowseEvent(URI.create(url)));
); }
if (url.startsWith("local://")) {
try {
var rootPackage = "atlantafx.sampler.page.";
var c = Class.forName(rootPackage + url.substring(8));
if (Page.class.isAssignableFrom(c)) {
DefaultEventBus.getInstance().publish(new NavEvent((Class<? extends Page>) c));
} else {
throw new IllegalArgumentException();
}
} catch (Exception ignored) {
System.err.println("Invalid local URL: \"" + url + "\"");
}
}
} }
e.consume(); e.consume();
}); });

@ -99,7 +99,7 @@ public final class AnimationsPage extends StackPane implements Page {
private VBox createOutline() { private VBox createOutline() {
var outline = new VBox(); var outline = new VBox();
outline.setSpacing(10); outline.setSpacing(10);
outline.setPadding(new Insets(0, 20, 0, 20)); outline.setPadding(new Insets(20));
outline.setMinWidth(OUTLINE_WIDTH); outline.setMinWidth(OUTLINE_WIDTH);
outline.setMaxWidth(OUTLINE_WIDTH); outline.setMaxWidth(OUTLINE_WIDTH);
Styles.appendStyle(outline, "-fx-background-color", "-color-bg-default"); Styles.appendStyle(outline, "-fx-background-color", "-color-bg-default");

@ -88,7 +88,10 @@ public final class DialogPage extends OutlinePage {
Pre-built dialog types for displaying information, warnings, and errors.""" Pre-built dialog types for displaying information, warnings, and errors."""
); );
return new ExampleBox(box, new Snippet(getClass(), 1), description); var example = new ExampleBox(box, new Snippet(getClass(), 1), description);
example.setAllowDisable(false);
return example;
} }
private ExampleBox exceptionDialogExample() { private ExampleBox exceptionDialogExample() {
@ -130,7 +133,10 @@ public final class DialogPage extends OutlinePage {
are thrown in JavaFX applications.""" are thrown in JavaFX applications."""
); );
return new ExampleBox(new HBox(button), new Snippet(getClass(), 2), description); var example = new ExampleBox(new HBox(button), new Snippet(getClass(), 2), description);
example.setAllowDisable(false);
return example;
} }
private ExampleBox confirmationDialogExample() { private ExampleBox confirmationDialogExample() {
@ -161,7 +167,10 @@ public final class DialogPage extends OutlinePage {
suggests the content of the dialog is seeking confirmation from the user.""" suggests the content of the dialog is seeking confirmation from the user."""
); );
return new ExampleBox(new HBox(button), new Snippet(getClass(), 3), description); var example = new ExampleBox(new HBox(button), new Snippet(getClass(), 3), description);
example.setAllowDisable(false);
return example;
} }
private ExampleBox textInputDialogExample() { private ExampleBox textInputDialogExample() {
@ -181,7 +190,10 @@ public final class DialogPage extends OutlinePage {
"A dialog that shows a text input control to the user." "A dialog that shows a text input control to the user."
); );
return new ExampleBox(new HBox(button), new Snippet(getClass(), 4), description); var example = new ExampleBox(new HBox(button), new Snippet(getClass(), 4), description);
example.setAllowDisable(false);
return example;
} }
private ExampleBox choiceDialogExample() { private ExampleBox choiceDialogExample() {
@ -202,7 +214,10 @@ public final class DialogPage extends OutlinePage {
A dialog that shows a list of choices to the user, from which they can pick one item at most.""" A dialog that shows a list of choices to the user, from which they can pick one item at most."""
); );
return new ExampleBox(new HBox(button), new Snippet(getClass(), 5), description); var example = new ExampleBox(new HBox(button), new Snippet(getClass(), 5), description);
example.setAllowDisable(false);
return example;
} }
private ExampleBox notificationNoHeaderDialogExample() { private ExampleBox notificationNoHeaderDialogExample() {
@ -243,6 +258,9 @@ public final class DialogPage extends OutlinePage {
"The header text can be hidden." "The header text can be hidden."
); );
return new ExampleBox(box, new Snippet(getClass(), 6), description); var example = new ExampleBox(box, new Snippet(getClass(), 6), description);
example.setAllowDisable(false);
return example;
} }
} }

@ -176,6 +176,9 @@ public class MessagePage extends OutlinePage {
which can be used to create a fancy banner, for example.""" which can be used to create a fancy banner, for example."""
); );
return new ExampleBox(box, new Snippet(getClass(), 4), description); var example = new ExampleBox(box, new Snippet(getClass(), 4), description);
example.setAllowDisable(false);
return example;
} }
} }

@ -94,7 +94,10 @@ public final class ModalPanePage extends OutlinePage {
[code]show()[/code] method, which is a convenience method for setting the content \ [code]show()[/code] method, which is a convenience method for setting the content \
of the modal pane and triggering its display state at the same time."""); of the modal pane and triggering its display state at the same time.""");
return new ExampleBox(box, new Snippet(getClass(), 1), description); var example = new ExampleBox(box, new Snippet(getClass(), 1), description);
example.setAllowDisable(false);
return example;
} }
private ExampleBox contentPositionExample() { private ExampleBox contentPositionExample() {
@ -163,7 +166,10 @@ public final class ModalPanePage extends OutlinePage {
The alignment and animated appearance of modal content can be changed \ The alignment and animated appearance of modal content can be changed \
via corresponding properties."""); via corresponding properties.""");
return new ExampleBox(box, new Snippet(getClass(), 1), description); var example = new ExampleBox(box, new Snippet(getClass(), 1), description);
example.setAllowDisable(false);
return example;
} }
private ExampleBox persistentExample() { private ExampleBox persistentExample() {
@ -192,7 +198,10 @@ public final class ModalPanePage extends OutlinePage {
or when the mouse is clicked outside the content area. [code]setPersistent()[/code] \ or when the mouse is clicked outside the content area. [code]setPersistent()[/code] \
property prevents this behavior and instead plays a bouncing animation."""); property prevents this behavior and instead plays a bouncing animation.""");
return new ExampleBox(box, new Snippet(getClass(), 3), description); var example = new ExampleBox(box, new Snippet(getClass(), 3), description);
example.setAllowDisable(false);
return example;
} }
private ExampleBox nestingExample() { private ExampleBox nestingExample() {
@ -226,7 +235,10 @@ public final class ModalPanePage extends OutlinePage {
the same behavior by stacking multiple modal panes and using the corresponding \ the same behavior by stacking multiple modal panes and using the corresponding \
[code]topViewOrder[/code] property value."""); [code]topViewOrder[/code] property value.""");
return new ExampleBox(box, new Snippet(getClass(), 4), description); var example = new ExampleBox(box, new Snippet(getClass(), 4), description);
example.setAllowDisable(false);
return example;
} }
private ExampleBox maximizedExample() { private ExampleBox maximizedExample() {
@ -248,7 +260,10 @@ public final class ModalPanePage extends OutlinePage {
To create a maximized dialog, simply use a content node such as [i]VBox[/i] \ To create a maximized dialog, simply use a content node such as [i]VBox[/i] \
that expands itself in both the horizontal and vertical directions."""); that expands itself in both the horizontal and vertical directions.""");
return new ExampleBox(box, new Snippet(getClass(), 5), description); var example = new ExampleBox(box, new Snippet(getClass(), 5), description);
example.setAllowDisable(false);
return example;
} }
private ExampleBox overflowedExample() { private ExampleBox overflowedExample() {
@ -302,7 +317,10 @@ public final class ModalPanePage extends OutlinePage {
The [i]ModalPane[/i] is already scrollable by default, but you can also use a \ The [i]ModalPane[/i] is already scrollable by default, but you can also use a \
[i]ScrollPane[/i] for the content node if needed."""); [i]ScrollPane[/i] for the content node if needed.""");
return new ExampleBox(box, new Snippet(getClass(), 6), description); var example = new ExampleBox(box, new Snippet(getClass(), 6), description);
example.setAllowDisable(false);
return example;
} }
private ExampleBox dialogPaneExample() { private ExampleBox dialogPaneExample() {
@ -348,7 +366,10 @@ public final class ModalPanePage extends OutlinePage {
and allows for the addition of arbitrary children.""" and allows for the addition of arbitrary children."""
); );
return new ExampleBox(box, new Snippet(getClass(), 8), description); var example = new ExampleBox(box, new Snippet(getClass(), 8), description);
example.setAllowDisable(false);
return example;
} }
private ExampleBox lightboxExample() { private ExampleBox lightboxExample() {

@ -88,7 +88,10 @@ public final class PopoverPage extends OutlinePage {
[i]Popover[/i] will move around with the parent window when the user drags it.""" [i]Popover[/i] will move around with the parent window when the user drags it."""
); );
return new ExampleBox(box, new Snippet(getClass(), 1), description); var example = new ExampleBox(box, new Snippet(getClass(), 1), description);
example.setAllowDisable(false);
return example;
} }
private ExampleBox positionExample() { private ExampleBox positionExample() {
@ -143,6 +146,9 @@ public final class PopoverPage extends OutlinePage {
appropriate ArrowLocation value..""" appropriate ArrowLocation value.."""
); );
return new ExampleBox(grid, new Snippet(getClass(), 2), description); var example = new ExampleBox(grid, new Snippet(getClass(), 2), description);
example.setAllowDisable(false);
return example;
} }
} }

@ -367,6 +367,9 @@ public final class ProgressIndicatorPage extends OutlinePage {
change the progress bar color while the task is in progress.""" change the progress bar color while the task is in progress."""
); );
return new ExampleBox(content, new Snippet(getClass(), 6), description); var example = new ExampleBox(content, new Snippet(getClass(), 6), description);
example.setAllowDisable(false);
return example;
} }
} }

@ -1,11 +1,11 @@
package atlantafx.sampler.page.components; package atlantafx.sampler.page.components;
import atlantafx.base.controls.PasswordTextField; import atlantafx.base.controls.PasswordTextField;
import atlantafx.base.controls.Tile;
import atlantafx.base.controls.ToggleSwitch; import atlantafx.base.controls.ToggleSwitch;
import atlantafx.base.theme.Styles; import atlantafx.base.theme.Styles;
import atlantafx.base.util.BBCodeParser; import atlantafx.base.util.BBCodeParser;
import atlantafx.sampler.Resources; import atlantafx.sampler.Resources;
import atlantafx.base.controls.Tile;
import atlantafx.sampler.page.ExampleBox; import atlantafx.sampler.page.ExampleBox;
import atlantafx.sampler.page.OutlinePage; import atlantafx.sampler.page.OutlinePage;
import atlantafx.sampler.page.Snippet; import atlantafx.sampler.page.Snippet;
@ -174,7 +174,7 @@ public class TilePage extends OutlinePage {
); );
var tgl2 = new ToggleSwitch(); var tgl2 = new ToggleSwitch();
tile2.setAction(tgl2); tile2.setAction(tgl2);
tile2.setActionHandler(() -> tgl2.setSelected(!tgl2.isSelected())); tile2.setActionHandler(tgl2::fire);
var tile3 = new Tile("Cache Size (Mb)", null); var tile3 = new Tile("Cache Size (Mb)", null);
var spinner = new Spinner<>(10, 100, 50); var spinner = new Spinner<>(10, 100, 50);
@ -187,7 +187,7 @@ public class TilePage extends OutlinePage {
); );
var tgl3 = new ToggleSwitch(); var tgl3 = new ToggleSwitch();
tile4.setAction(tgl3); tile4.setAction(tgl3);
tile4.setActionHandler(() -> tgl3.setSelected(!tgl3.isSelected())); tile4.setActionHandler(tgl3::fire);
var box = new VBox(tile1, tile2, tile3, new Separator(), tile4); var box = new VBox(tile1, tile2, tile3, new Separator(), tile4);
//snippet_3:end //snippet_3:end

@ -63,7 +63,10 @@ public final class TooltipPage extends OutlinePage {
modified to show plain text to the user.""" modified to show plain text to the user."""
); );
return new ExampleBox(box, new Snippet(getClass(), 1), description); var example = new ExampleBox(box, new Snippet(getClass(), 1), description);
example.setAllowDisable(false);
return example;
} }
private ExampleBox positionExample() { private ExampleBox positionExample() {
@ -98,7 +101,10 @@ public final class TooltipPage extends OutlinePage {
The point can be set to a corner of the popup window or a corner of its content.""" The point can be set to a corner of the popup window or a corner of its content."""
); );
return new ExampleBox(box, new Snippet(getClass(), 2), description); var example = new ExampleBox(box, new Snippet(getClass(), 2), description);
example.setAllowDisable(false);
return example;
} }
private Label createLabel(String text) { private Label createLabel(String text) {

@ -49,10 +49,11 @@ public final class TypographyPage extends OutlinePage {
addPageHeader(); addPageHeader();
addFormattedText(""" addFormattedText("""
Because AtlantaFX is also distributed as a single CSS file, it does not come \ 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 \ 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 \ 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 [url=local://general.BBCodePage]BBCodeParser[/url].""",
true
); );
addSection("Font Size", fontSizeExample()); addSection("Font Size", fontSizeExample());
addSection("Font Weight", fontWeightExample()); addSection("Font Weight", fontWeightExample());

@ -68,7 +68,7 @@
-fx-min-height: 2.1em; -fx-min-height: 2.1em;
-fx-pref-height: 2.1em; -fx-pref-height: 2.1em;
-fx-max-height: 2.1em; -fx-max-height: 2.1em;
-fx-padding: 0 0 0 1.2em; -fx-padding: 0 6px 0 1.2em;
-fx-border-color: -color-border-muted; -fx-border-color: -color-border-muted;
-fx-border-width: 0 0 0 1; -fx-border-width: 0 0 0 1;
@ -106,5 +106,12 @@
-fx-icon-code: mdmz-remove; -fx-icon-code: mdmz-remove;
} }
} }
.tag {
-fx-padding: 2px 4px 2px 4px;
-fx-background-radius: 4px;
-fx-font-size: 0.75em;
-fx-background-color: -color-success-subtle;
}
} }
} }