diff --git a/README.md b/README.md index 2f17e4f8..d0bed89b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ [![JFXCentral](https://img.shields.io/badge/Find_me_on-JFXCentral-blue?logo=googlechrome&logoColor=white)](https://www.jfx-central.com/libraries/gemsfx) [![Maven Central](https://img.shields.io/maven-central/v/com.dlsc.gemsfx/gemsfx?color=brightgreen)](https://search.maven.org/search?q=g:com.dlsc.gemsfx%20AND%20a:gemsfx) [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +[![Java Version](https://img.shields.io/badge/Java_Version-17-ff69b4)](https://github.com/openjdk/jdk) +[![JavaFX Version](https://img.shields.io/badge/JavaFX_Version-22-brightgreen)](https://github.com/openjdk/jfx) # GemsFX @@ -8,24 +10,16 @@ GemsFX is a collection of custom controls and utilities for JavaFX. ## Quick Links -- [Date & Time Controls](#date-time-controls) +- Date & Time Controls > [CalendarView](#calendar-view), [CalendarPicker](#calendar-picker), [DateRangeView](#date-range-view), [DateRangePicker](#date-range-picker),[YearView](#year-view), [YearPicker](#year-picker), [YearMonthView](#year-month-view), [YearMonthPicker](#year-month-picker), [TimePicker](#time-picker), [DurationPicker](#duration-picker) -- [Text Input Controls](#text-input-controls) +- Text Input Controls > [SearchTextField](#search-text-field), [SearchField](#search-field), [EmailField](#email-field), [TagsField](#tags-field), [ExpandingTextArea](#expanding-text-area), [ResizableTextArea](#resizable-text-area), [LimitedTextArea](#limited-text-area) -- [Dialogs & Notifications](#dialogs-notifications) - > [DialogPane](#dialog-pane), [InfoCenterPane](#info-center-pane) - -## SVGImageView - -A control used for rendering SVG image files. Utilizing the [jsvg](https://github.com/weisJ/jsvg) library, ensuring -high-definition quality even when scaled. - -- Packaging Note: Not suitable for native packaging yet due to AWT dependency. -- Content Note: Static only for now; future jsvg updates may add animation. -- Development Note: [jsvg](https://github.com/weisJ/jsvg) is evolving and does not yet support all features of the SVG - specification. - -![SVGImageView](gemsfx/docs/svg-image-view.png) +- Advanced Panes + > [DialogPane](#dialog-pane), [DrawerStackPane](#drawer-stack-pane), [PowerPane](#power-pane), [ResponsivePane](#responsive-pane) +- Image controls + > [PhotoView](#photo-view), [PaymentOptionControls](#payment-option-controls), [SVGImageView](#svg-image-view) +- Other Controls + > [CircleProgressIndicator](#circle-progress-indicator), [FilterView](#filter-view), [InfoCenterPane](#info-center-pane), [StripView](#strip-view), [Spacer](#spacer), [ScreensView](#screens-view), [SessionManager](#session-manager), [StageManager](#stage-manager), [TreeNodeView](#tree-node-view), [MultiColumnListView](#multi-column-list-view) ## CalendarView @@ -84,6 +78,7 @@ is selectable. ![YearView](gemsfx/docs/year-view.png) ## YearPicker + A view for picking a year from a dropdown showing the year view control. @@ -91,6 +86,7 @@ A view for picking a year from a dropdown showing the year view control. ![YearMonthPicker](gemsfx/docs/year-picker.png) ## YearMonthView + A view for displaying the months of a given year. The user can quickly switch between years. Properties @@ -99,6 +95,7 @@ are available to restrict the selection to an earliest and a latest month. ![YearMonthPicker](gemsfx/docs/year-month-view.png) ## YearMonthPicker + A control for specifying the month of a year (see time API class "YearMonth"). It is very similar to the standard date @@ -108,6 +105,7 @@ and actually inherits a lot of styling attributes from it. ![YearMonthPicker](gemsfx/docs/year-month-picker.png) ## TimePicker + A small control used for entering a time. The control can be configured with a "step rate" for the minutes field (e.g. " @@ -125,6 +123,7 @@ get increased when the minute field rolls over from 59 to 0 or decreased when th ![TimePicker](gemsfx/docs/time-picker.png) ## DurationPicker + A small control used for entering a duration. The control can be configured to only allow a duration within the range @@ -137,78 +136,74 @@ filling fields with leading zeros, etc.. ![DurationPicker](gemsfx/docs/duration-picker.png) ## SearchTextField + A textfield that has been nicely decorated to express that it is used for performing searches. ![SearchTextField](gemsfx/docs/search-text-field.png) +## Search Field -## Spacer + -Spacer extends Region and is designed to create flexible spaces in container layouts, especially in HBox and VBox. -Within an HBox, the Spacer grows horizontally. Within a VBox, it grows vertically. When the activeProperty is set to -false, the Spacer will not grow. +An auto-suggest text field with a behaviour similar to the spotlight search experience on Mac. While typing the field +will automatically finish the entered text if it has a search result where the name starts with the exact typed text. At +any time the typed text and the auto-completed text will be visually distinguishable. The field is also capable of +creating a new object for the entered text if no result can be found. For detailed +instructions [read the WIKI page](https://github.com/dlsc-software-consulting-gmbh/GemsFX/wiki/SearchField). -![Spacer](gemsfx/docs/spacer.png) +![SearchField](gemsfx/docs/search-field.png) -## StripView +## Email Field -A view for horizontally positioning a number of nodes, one for each item added to the view's model. Scroll buttons will -become visible on either side of the view if the available width is not sufficient to show all items / nodes. Scrolling -is animated (can be turned off). The nodes on either side are fading out so that the scroll controls are completely -visible. The view also supports the single selection of an item. + -![StripView](gemsfx/docs/strip-view.png) +A text field that has been nicely decorated to express that it is used for entering email addresses. The field will +validate the entered text and show an error message if the text is not a valid email address. -## InfoCenterPane +![EmailField](gemsfx/docs/email-field.png) -A view for displaying (groups of) notifications. Incoming / new notifications slide-in via an animation. Each group can -have its own factory for the creation of notification views. A group with multiple notifications can be shown stacked or -expanded. A threshold can be defined to determine the maximum number of notifications that can be shown. If the -notifcation count is higher than the threshold then the user can switch to a list view showing them all. Groups can be -pinned so that they always stay in the top position without being scrolled out of view. +## Tags Field -![InfoCenterPane](gemsfx/docs/info-center-pane.png) + -## ScreensView +An extension of the SearchField control that supports the creation of tags. Selected values are converted into tags when +the user hits enter, the right arrow key, or tab. The API of this control allows applications to retrieve the tags, or +to monitor the selection state of the tags. The control uses a FlowPane for its layout, which allows the tags to span +multiple rows. -A small control that can be used to display the screen geometries as seen by the application. The view can also -display the application's windows, and some arbitrary shapes (might be useful for debugging purposes). +![TagsField](gemsfx/docs/tags-field.png) -![ScreensView](gemsfx/docs/screens-view.png) +## Expanding Text Area -## Stage Manager +A customized text area that grows based on its text content. The text area will never show vertical or horizontal +scrollbars. -The `StageManager` class is a utility class that keeps track of a stage's location and dimensions. These values -will be stored and used across user sessions via the `java.util.prefs` API. +![ExpandingTextArea](gemsfx/docs/expanding-text-area.png) -## Session Manager +## Resizable Text Area -The `SessionManager` class is a utility class that can be used to monitor observables and persist them across user -sessions. This can be useful, for example, for storing and restoring the position of the divider of a SplitPane. + -## Search Field +A custom control that wraps a text area and adds a resize handle to the lower right corner of it. The area can be +configured to be resizable in vertical, horizontal, or both directions. -An auto-suggest text field with a behaviour similar to the spotlight search experience on Mac. While typing the field -will automatically finish the entered text if it has a search result where the name starts with the exact typed text. At -any time the typed text and the auto-completed text will be visually distinguishable. The field is also capable of -creating a new object for the entered text if no result can be found. For detailed -instructions [read the WIKI page](https://github.com/dlsc-software-consulting-gmbh/GemsFX/wiki/SearchField). +![ResizableTextArea](gemsfx/docs/resizable-text-area.png) -![SearchField](gemsfx/docs/search-field.png) +## Limited Text Area -## Tags Field + -An extension of the SearchField control that supports the creation of tags. Selected values are converted into tags when -the user hits enter, the right arrow key, or tab. The API of this control allows applications to retrieve the tags, or -to monitor the selection state of the tags. The control uses a FlowPane for its layout, which allows the tags to span -multiple rows. +LimitedTextArea is derived from ResizableTextArea and offers a character-limiting feature, +accompanied by a character counter that indicates the remaining number of characters. -![TagsField](gemsfx/docs/tags-field.png) +![LimitedTextArea](gemsfx/docs/limited-text-area.png) ## Dialog Pane + + The class DialogPane can be used as a layer on top of any application. It offers various methods to display different types of dialogs. @@ -223,22 +218,47 @@ types of dialogs. ![DialogPane](gemsfx/docs/dialog-pane.png) -## ResizableTextArea +## DrawerStackPane -A custom control that wraps a text area and adds a resize handle to the lower right corner of it. The area can be -configured to be resizable in vertical, horizontal, or both directions. + -![ResizableTextArea](gemsfx/docs/resizable-text-area.png) +A stackpane with an optional node that can be shown inside a drawer. The drawer is animated and can slide in and out. +When the drawer is showing a semi-transparent glass pane will cover the background. In addition the last height of the +drawer can be persisted via the preferences API so that next time the drawer will show itself like in the last user +session. -## Expanding Text Area +![DrawerStackPane](gemsfx/docs/drawer-stackpane.png) -A customized text area that grows based on its text content. The text area will never show vertical or horizontal -scrollbars. +## PowerPane -![ExpandingTextArea](gemsfx/docs/expanding-text-area.png) + + +The PowerPane is a versatile container that amalgamates specialized panes such as the InfoCenterPane, DialogPane, +DrawerStackPane, and HiddenSidesPane. It serves as an ideal foundation for crafting feature-rich client applications. + +![PowerPane](gemsfx/docs/power-pane.png) + +## ResponsivePane + + + +ResponsivePane is a container that allows for responsive behavior of a sidebar and a main content panel. +Depending on the specified position of the sidebar (LEFT or RIGHT), it will automatically adjust its visibility +based on the width of the pane. When the window width is narrow, the sidebar is hidden, and only the content panel is +shown. +When the window width is moderate, both a small sidebar and a large sidebar, along with the content panel, are +displayed. +When the window width is wide, only the large sidebar is shown. +Similarly, if the sidebar is positioned at the TOP or BOTTOM, its visibility will be adjusted based on the height of the +pane. +However, it is also possible to force the sidebar to be displayed regardless of the window size. + +![ResponsivePane](gemsfx/docs/responsive-pane.png) ## Photo View + + A control for adding and editing a user profile photo (or whatever). The user can click on the control to choose an image file via a file chooser (replacable) or via drag and drop. Once added the user can move the image around and zoom in / out. @@ -253,27 +273,117 @@ be removed by pressing DELETE or BACK_SPACE. ## Payment Option Controls + + A specialized subclass of ImageView that can be used to display different graphics for different payment options. Graphics provided by Gregoire Segretain (https://www.sketchappsources.com/contributor/gregoiresgt) ![LightOption](gemsfx/docs/payment-options-light.png) ![DarkOption](gemsfx/docs/payment-options-dark.png) -## DrawerStackPane +## SVGImageView -A stackpane with an optional node that can be shown inside a drawer. The drawer is animated and can slide in and out. -When the drawer is showing a semi-transparent glass pane will cover the background. In addition the last height of the -drawer can be persisted via the preferences API so that next time the drawer will show itself like in the last user -session. + -![DrawerStackPane](gemsfx/docs/drawer-stackpane.png) +A control used for rendering SVG image files. Utilizing the [jsvg](https://github.com/weisJ/jsvg) library, ensuring +high-definition quality even when scaled. + +- Packaging Note: Not suitable for native packaging yet due to AWT dependency. +- Content Note: Static only for now; future jsvg updates may add animation. +- Development Note: [jsvg](https://github.com/weisJ/jsvg) is evolving and does not yet support all features of the SVG + specification. + +![SVGImageView](gemsfx/docs/svg-image-view.png) + +## Circle Progress Indicator + + +A control for displaying a circular progress indicator. The control can be configured to show a percentage value or a +text value. The control can also be configured to show a progress bar. + +![CircleProgressIndicator](gemsfx/docs/circle-progress-indicator.png) ## FilterView + + A control for filtering the content of an observable list. Works in combination with TableView, ListView, or any control that is based on observable lists. ![FilterView](gemsfx/docs/filter-view.png) +## InfoCenterPane + + + +A view for displaying (groups of) notifications. Incoming / new notifications slide-in via an animation. Each group can +have its own factory for the creation of notification views. A group with multiple notifications can be shown stacked or +expanded. A threshold can be defined to determine the maximum number of notifications that can be shown. If the +notifcation count is higher than the threshold then the user can switch to a list view showing them all. Groups can be +pinned so that they always stay in the top position without being scrolled out of view. + +![InfoCenterPane](gemsfx/docs/info-center-pane.png) + +## StripView + + + +A view for horizontally positioning a number of nodes, one for each item added to the view's model. Scroll buttons will +become visible on either side of the view if the available width is not sufficient to show all items / nodes. Scrolling +is animated (can be turned off). The nodes on either side are fading out so that the scroll controls are completely +visible. The view also supports the single selection of an item. + +![StripView](gemsfx/docs/strip-view.png) + +## Spacer + + + +Spacer extends Region and is designed to create flexible spaces in container layouts, especially in HBox and VBox. +Within an HBox, the Spacer grows horizontally. Within a VBox, it grows vertically. When the activeProperty is set to +false, the Spacer will not grow. + +![Spacer](gemsfx/docs/spacer.png) + +## ScreensView + + + +A small control that can be used to display the screen geometries as seen by the application. The view can also +display the application's windows, and some arbitrary shapes (might be useful for debugging purposes). + +![ScreensView](gemsfx/docs/screens-view.png) + +## Session Manager + + + +The `SessionManager` class is a utility class that can be used to monitor observables and persist them across user +sessions. This can be useful, for example, for storing and restoring the position of the divider of a SplitPane. + +## Stage Manager + + + +The `StageManager` class is a utility class that keeps track of a stage's location and dimensions. These values +will be stored and used across user sessions via the `java.util.prefs` API. + +## Tree Node View + + +A view for displaying a tree of nodes. + +![TreeNodeView](gemsfx/docs/tree-node-view.png) + + +## Multi Column List View + + + +A view for displaying multiple columns where each column consists of a header control and a ListView. +The control allows the user to rearrange the items in each ListView and also to drag and drop items from one column to another. + +![MultiColumnListView](gemsfx/docs/multi-column-list-view.png) + ## Running the demos You can run the demos using Maven by typing any of the following lines into your diff --git a/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/ResponsivePaneApp.java b/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/ResponsivePaneApp.java index 3aa013d5..13a3ec0a 100644 --- a/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/ResponsivePaneApp.java +++ b/gemsfx-demo/src/main/java/com/dlsc/gemsfx/demo/ResponsivePaneApp.java @@ -17,7 +17,7 @@ public class ResponsivePaneApp extends Application { - private final ResponsivePane sideBarPane = new ResponsivePane(); + private final ResponsivePane responsivePane = new ResponsivePane(); private StackPane mainContent; private Region smallSidebar; @@ -28,7 +28,7 @@ public void start(Stage stage) throws Exception { Label widthLabel = new Label(); widthLabel.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE); widthLabel.setStyle("-fx-background-color: pink; -fx-alignment: center; -fx-padding: 5px 10px;"); - widthLabel.textProperty().bind(Bindings.createStringBinding(() -> String.format("SideBarPane: %.0f x %.0f", sideBarPane.getWidth(), sideBarPane.getHeight()), sideBarPane.widthProperty(), sideBarPane.heightProperty())); + widthLabel.textProperty().bind(Bindings.createStringBinding(() -> String.format("ResponsivePane: %.0f x %.0f", responsivePane.getWidth(), responsivePane.getHeight()), responsivePane.widthProperty(), responsivePane.heightProperty())); mainContent = new StackPane(widthLabel); mainContent.setStyle("-fx-background-color: #eeeeee;"); @@ -42,15 +42,15 @@ public void start(Stage stage) throws Exception { largeSidebar.setPrefSize(150, 150); largeSidebar.setStyle("-fx-background-color: rgba(43,83,241,0.5); -fx-border-color: white; -fx-border-insets: 1px;"); - sideBarPane.setSmallSidebar(smallSidebar); - sideBarPane.setLargeSidebar(largeSidebar); - sideBarPane.setContent(mainContent); - sideBarPane.setForceLargeSidebarDisplay(true); - sideBarPane.setLargeSidebarCoversSmall(false); - sideBarPane.setGap(10); - sideBarPane.setStyle("-fx-background-color: white;"); + responsivePane.setSmallSidebar(smallSidebar); + responsivePane.setLargeSidebar(largeSidebar); + responsivePane.setContent(mainContent); + responsivePane.setForceLargeSidebarDisplay(true); + responsivePane.setLargeSidebarCoversSmall(false); + responsivePane.setGap(10); + responsivePane.setStyle("-fx-background-color: white;"); - BorderPane borderPane = new BorderPane(sideBarPane); + BorderPane borderPane = new BorderPane(responsivePane); borderPane.setRight(createControlPanel()); Scene scene = new Scene(borderPane); @@ -74,18 +74,18 @@ public Side fromString(String s) { return null; } }); - sideComboBox.valueProperty().bindBidirectional(sideBarPane.sideProperty()); + sideComboBox.valueProperty().bindBidirectional(responsivePane.sideProperty()); sideComboBox.setMaxWidth(Double.MAX_VALUE); Spinner gapSpinner = new Spinner<>(0, 10, 0, 2); - sideBarPane.gapProperty().bind(gapSpinner.valueProperty()); + responsivePane.gapProperty().bind(gapSpinner.valueProperty()); gapSpinner.setMaxWidth(Double.MAX_VALUE); CheckBox largeSidebarCoverCheckBox = new CheckBox("Large Covers Small"); - largeSidebarCoverCheckBox.selectedProperty().bindBidirectional(sideBarPane.largeSidebarCoversSmallProperty()); + largeSidebarCoverCheckBox.selectedProperty().bindBidirectional(responsivePane.largeSidebarCoversSmallProperty()); CheckBox forceLargeDisplayCheckBox = new CheckBox("Force Display Large"); - forceLargeDisplayCheckBox.selectedProperty().bindBidirectional(sideBarPane.forceLargeSidebarDisplayProperty()); + forceLargeDisplayCheckBox.selectedProperty().bindBidirectional(responsivePane.forceLargeSidebarDisplayProperty()); VBox controlBox = new VBox(new Label("Side"), sideComboBox, new Label("Gap"), gapSpinner, new Label("Content PrefSize"), createSizeInfoField(mainContent), new Label("Small Sidebar PrefSize"), diff --git a/gemsfx/docs/circle-progress-indicator.png b/gemsfx/docs/circle-progress-indicator.png new file mode 100644 index 00000000..08179e37 Binary files /dev/null and b/gemsfx/docs/circle-progress-indicator.png differ diff --git a/gemsfx/docs/email-field.png b/gemsfx/docs/email-field.png new file mode 100644 index 00000000..89e29872 Binary files /dev/null and b/gemsfx/docs/email-field.png differ diff --git a/gemsfx/docs/limited-text-area.png b/gemsfx/docs/limited-text-area.png new file mode 100644 index 00000000..a11ba918 Binary files /dev/null and b/gemsfx/docs/limited-text-area.png differ diff --git a/gemsfx/docs/multi-column-list-view.png b/gemsfx/docs/multi-column-list-view.png new file mode 100644 index 00000000..fdb400fc Binary files /dev/null and b/gemsfx/docs/multi-column-list-view.png differ diff --git a/gemsfx/docs/power-pane.png b/gemsfx/docs/power-pane.png new file mode 100644 index 00000000..1b8ee0d6 Binary files /dev/null and b/gemsfx/docs/power-pane.png differ diff --git a/gemsfx/docs/responsive-pane.png b/gemsfx/docs/responsive-pane.png new file mode 100644 index 00000000..67a80c28 Binary files /dev/null and b/gemsfx/docs/responsive-pane.png differ diff --git a/gemsfx/docs/tree-node-view.png b/gemsfx/docs/tree-node-view.png new file mode 100644 index 00000000..dafaf018 Binary files /dev/null and b/gemsfx/docs/tree-node-view.png differ diff --git a/gemsfx/src/main/java/com/dlsc/gemsfx/ResponsivePane.java b/gemsfx/src/main/java/com/dlsc/gemsfx/ResponsivePane.java index 3b99b515..6d369f1c 100644 --- a/gemsfx/src/main/java/com/dlsc/gemsfx/ResponsivePane.java +++ b/gemsfx/src/main/java/com/dlsc/gemsfx/ResponsivePane.java @@ -16,6 +16,16 @@ import java.util.List; import java.util.Objects; +/** + * ResponsivePane is a container that allows for responsive behavior of a sidebar and a main content panel. + * Depending on the specified position of the sidebar (LEFT or RIGHT), it will automatically adjust its visibility + * based on the width of the pane. When the window width is narrow, the sidebar is hidden, and only the content panel is shown. + * When the window width is moderate, both a small sidebar and a large sidebar, along with the content panel, are displayed. + * When the window width is wide, only the large sidebar is shown. + * Similarly, if the sidebar is positioned at the TOP or BOTTOM, its visibility will be adjusted based on the height of the pane. + * However, it is also possible to force the sidebar to be displayed regardless of the window size. + * + */ public class ResponsivePane extends Pane { private static final Side DEFAULT_SIDE = Side.LEFT; diff --git a/gemsfx/src/main/java/com/dlsc/gemsfx/treeview/TreeNodeView.java b/gemsfx/src/main/java/com/dlsc/gemsfx/treeview/TreeNodeView.java index d57c1902..d9ac3d46 100644 --- a/gemsfx/src/main/java/com/dlsc/gemsfx/treeview/TreeNodeView.java +++ b/gemsfx/src/main/java/com/dlsc/gemsfx/treeview/TreeNodeView.java @@ -26,6 +26,14 @@ import java.util.List; import java.util.Objects; + +/** + * A visual control for displaying trees. + *

+ * Built on the {@link TreeNode} class, this control visualizes hierarchical structures, allowing nodes to have children. + *

+ * Customizable in layout, alignment, and style, it's ideal for representing data like file systems or organizational charts. + */ public class TreeNodeView extends Control { private static final int DEFAULT_CELL_WIDTH = 60; private static final int DEFAULT_CELL_HEIGHT = 30; @@ -282,7 +290,7 @@ public void setVgap(double vgap) { this.vgap.set(vgap); } - private final DoubleProperty nodeLineGap = new StyleableDoubleProperty(DEFAULT_NODE_LINE_GAP){ + private final DoubleProperty nodeLineGap = new StyleableDoubleProperty(DEFAULT_NODE_LINE_GAP) { @Override public CssMetaData getCssMetaData() { return StyleableProperties.NODE_LINE_GAP; @@ -356,7 +364,7 @@ public enum LayoutType { COMPACT; } - private final ObjectProperty layoutType = new StyleableObjectProperty<>(DEFAULT_LAYOUT_TYPE){ + private final ObjectProperty layoutType = new StyleableObjectProperty<>(DEFAULT_LAYOUT_TYPE) { @Override public CssMetaData getCssMetaData() { return StyleableProperties.LAYOUT_TYPE; @@ -404,7 +412,7 @@ public enum LayoutDirection { BOTTOM_TO_TOP; } - private final ObjectProperty layoutDirection = new StyleableObjectProperty<>(DEFAULT_LAYOUT_DIRECTION){ + private final ObjectProperty layoutDirection = new StyleableObjectProperty<>(DEFAULT_LAYOUT_DIRECTION) { @Override public CssMetaData getCssMetaData() { return StyleableProperties.LAYOUT_DIRECTION;