--- a/modules/javafx.graphics/src/main/java/javafx/scene/layout/HeaderBar.java +++ b/modules/javafx.graphics/src/main/java/javafx/scene/layout/HeaderBar.java + +/** + * A client-area header bar that is used as a replacement for the system-provided header bar in stages + * with the {@link StageStyle#EXTENDED} style. This class enables the click-and-drag to move and + * double-click to maximize behaviors that are usually afforded by system-provided header bars. + * The entire {@code HeaderBar} background is draggable by default, but its content is not. Applications + * can specify draggable content nodes of the {@code HeaderBar} with the {@link #setDragType(Node, HeaderDragType)} + * method. + *
+ * {@code HeaderBar} is a layout container that allows applications to place scene graph nodes in three areas: + * {@link #leadingProperty() leading}, {@link #centerProperty() center}, and {@link #trailingProperty() trailing}. + * All areas can be {@code null}. The default {@link #minHeightProperty() minHeight} of the {@code HeaderBar} is + * set to match the height of the platform-specific default header buttons. + * + *
+ * An application may set constraints on individual children to customize their layout. + * For each constraint, {@code HeaderBar} provides static getter and setter methods. + *
Constraint | Type | Description |
---|---|---|
alignment | {@link Pos} | + *The alignment of the child within its area of the {@code HeaderBar}. | + *
margin | + *{@link Insets} | Margin space around the outside of the child. | + *
+ * If a child should instead be centered with respect to the {@code center} area only, a possible solution is to + * place another layout container like {@link BorderPane} in the {@code center} area, and then center the child + * within the other layout container. + * + *
{@code + * public class MyApp extends Application { + * @Override + * public void start(Stage stage) { + * var button = new Button("My button"); + * HeaderBar.setAlignment(button, Pos.CENTER_LEFT); + * HeaderBar.setMargin(button, new Insets(5)); + * + * var headerBar = new HeaderBar(); + * headerBar.setCenter(button); + * + * var root = new BorderPane(); + * root.setTop(headerBar); + * + * stage.setScene(new Scene(root)); + * stage.initStyle(StageStyle.EXTENDED); + * stage.show(); + * } + * } + * }+ * + * @since 25 + * @deprecated This is a preview feature which may be changed or removed in a future release. + */ +@Deprecated(since = "25") +public class HeaderBar extends Region { + + /** + * Specifies the {@code HeaderDragType} of the child, indicating whether it is a draggable + * part of the {@code HeaderBar}. + *
+ * Setting the value to {@code null} will remove the flag. + * + * @param child the child node + * @param value the {@code HeaderDragType}, or {@code null} to remove the flag + */ + public static void setDragType(Node child, HeaderDragType value); + + /** + * Returns the {@code HeaderDragType} of the specified child. + * + * @param child the child node + * @return the {@code HeaderDragType}, or {@code null} if not set + */ + public static HeaderDragType getDragType(Node child); + + /** + * Specifies the {@code HeaderButtonType} of the child, indicating its semantic use in the header bar. + *
+ * This property can be set on any {@link Node}. Specifying a header button type also provides the behavior + * associated with the button type. If the default behavior is not desired, applications can register an + * event filter on the child node that consumes the {@link MouseEvent#MOUSE_RELEASED} event. + * + * @param child the child node + * @param value the {@code HeaderButtonType}, or {@code null} + */ + public static void setButtonType(Node child, HeaderButtonType value); + + /** + * Returns the {@code HeaderButtonType} of the specified child. + * + * @param child the child node + * @return the {@code HeaderButtonType}, or {@code null} + */ + public static HeaderButtonType getButtonType(Node child); + + /** + * Sentinel value that can be used for {@link #setPrefButtonHeight(Stage, double)} to indicate that + * the platform should choose the platform-specific default button height. + */ + public static final double USE_DEFAULT_SIZE = -1; + + /** + * Specifies the preferred height of the system-provided header buttons of the specified stage. + *
+ * Any value except zero and {@link #USE_DEFAULT_SIZE} is only a hint for the platform window toolkit. + * The platform might accommodate the preferred height in various ways, such as by stretching the header + * buttons (fully or partially) to fill the preferred height, or centering the header buttons (fully or + * partially) within the preferred height. Some platforms might only accommodate the preferred height + * within platform-specific constraints, or ignore it entirely. + *
+ * Setting the preferred height to zero hides the system-provided header buttons, allowing applications to + * use custom header buttons instead (see {@link #setButtonType(Node, HeaderButtonType)}). + *
+ * The default value {@code #USE_DEFAULT_SIZE} indicates that the platform should choose the button height. + * + * @param stage the {@code Stage} + * @param height the preferred height, or 0 to hide the system-provided header buttons + */ + public static void setPrefButtonHeight(Stage stage, double height); + + /** + * Returns the preferred height of the system-provided header buttons of the specified stage. + * + * @param stage the {@code Stage} + * @return the preferred height of the system-provided header buttons + */ + public static double getPrefButtonHeight(Stage stage); + + /** + * Sets the alignment for the child when contained in a {@code HeaderBar}. + * If set, will override the header bar's default alignment for the child's position. + * Setting the value to {@code null} will remove the constraint. + * + * @param child the child node + * @param value the alignment position + */ + public static void setAlignment(Node child, Pos value); + + /** + * Returns the child's alignment in the {@code HeaderBar}. + * + * @param child the child node + * @return the alignment position for the child, or {@code null} if no alignment was set + */ + public static Pos getAlignment(Node child); + + /** + * Sets the margin for the child when contained in a {@code HeaderBar}. + * If set, the header bar will lay it out with the margin space around it. + * Setting the value to {@code null} will remove the constraint. + * + * @param child the child node + * @param value the margin of space around the child + */ + public static void setMargin(Node child, Insets value); + + /** + * Returns the child's margin. + * + * @param child the child node + * @return the margin for the child, or {@code null} if no margin was set + */ + public static Insets getMargin(Node child); + + /** + * Creates a new {@code HeaderBar}. + */ + public HeaderBar(); + + /** + * Creates a new {@code HeaderBar} with the specified children. + * + * @param leading the leading node + * @param center the center node + * @param trailing the trailing node + */ + public HeaderBar(Node leading, Node center, Node trailing); + + /** + * Describes the size of the left system-reserved inset, which is an area reserved for the iconify, maximize, + * and close window buttons. If there are no window buttons on the left side of the window, the returned area + * is an empty {@code Dimension2D}. + *
+ * Note that the left system inset refers to the left side of the window, independent of layout orientation.
+ */
+ private final ReadOnlyObjectWrapper
+ * Note that the right system inset refers to the right side of the window, independent of layout orientation.
+ */
+ private final ReadOnlyObjectWrapper
+ * By default, {@link #minHeightProperty() minHeight} is set to the value of {@code minSystemHeight},
+ * unless {@code minHeight} is explicitly set by a stylesheet or application code.
+ */
+ private final ReadOnlyDoubleWrapper minSystemHeight;
+
+ public final ReadOnlyDoubleProperty minSystemHeightProperty();
+
+ public final double getMinSystemHeight();
+
+ /**
+ * The leading area of the {@code HeaderBar}.
+ *
+ * The leading area corresponds to the left area in a left-to-right layout, and to the right area
+ * in a right-to-left layout.
+ *
+ * @defaultValue {@code null}
+ */
+ private final ObjectProperty
+ * The trailing area corresponds to the right area in a left-to-right layout, and to the left area
+ * in a right-to-left layout.
+ *
+ * @defaultValue {@code null}
+ */
+ private final ObjectProperty
+ * Applications that use a single {@code HeaderBar} extending the entire width of the window should
+ * set this property to {@code true} to prevent the header buttons from overlapping the content of the
+ * {@code HeaderBar}.
+ *
+ * @defaultValue {@code true}
+ * @see #trailingSystemPaddingProperty() trailingSystemPadding
+ */
+ private final BooleanProperty leadingSystemPadding;
+
+ public final BooleanProperty leadingSystemPaddingProperty();
+
+ public final boolean isLeadingSystemPadding();
+
+ public final void setLeadingSystemPadding(boolean value);
+
+ /**
+ * Specifies whether additional padding should be added to the trailing side of the {@code HeaderBar}.
+ * The size of the additional padding corresponds to the size of the system-reserved area that contains
+ * the default header buttons (iconify, maximize, and close). If the system-reserved area contains no
+ * header buttons, no additional padding is added to the trailing side of the {@code HeaderBar}.
+ *
+ * Applications that use a single {@code HeaderBar} extending the entire width of the window should
+ * set this property to {@code true} to prevent the header buttons from overlapping the content of the
+ * {@code HeaderBar}.
+ *
+ * @defaultValue {@code true}
+ * @see #leadingSystemPaddingProperty() leadingSystemPadding
+ */
+ private final BooleanProperty trailingSystemPadding;
+
+ public final BooleanProperty trailingSystemPaddingProperty();
+
+ public final boolean isTrailingSystemPadding();
+
+ public final void setTrailingSystemPadding(boolean value);
+}
--- a/modules/javafx.graphics/src/main/java/javafx/scene/layout/HeaderButtonType.java
+++ b/modules/javafx.graphics/src/main/java/javafx/scene/layout/HeaderButtonType.java
+
+/**
+ * Identifies the semantic type of a button in a custom {@link HeaderBar}, which enables integrations
+ * with the platform window manager. For example, hovering over a {@link #MAXIMIZE} button on Windows
+ * will summon snap layouts.
+ *
+ * @since 25
+ * @deprecated This is a preview feature which may be changed or removed in a future release.
+ * @see HeaderBar#setButtonType(Node, HeaderButtonType)
+ */
+@Deprecated(since = "25")
+public enum HeaderButtonType {
+
+ /**
+ * Identifies the iconify button.
+ *
+ * @see Stage#isIconified()
+ * @see Stage#setIconified(boolean)
+ */
+ ICONIFY,
+
+ /**
+ * Identifies the maximize button.
+ *
+ * This button toggles the {@link Stage#isMaximized()} or {@link Stage#isFullScreen()} property,
+ * depending on platform-specific invocation semantics. For example, on macOS the button will
+ * put the window into full-screen mode by default, but maximize it to cover the desktop when
+ * the option key is pressed.
+ *
+ * If the window is maximized, the button will have the {@code maximized} pseudo-class.
+ *
+ * @see Stage#isMaximized()
+ * @see Stage#setMaximized(boolean)
+ * @see Stage#isFullScreen()
+ * @see Stage#setFullScreen(boolean)
+ */
+ MAXIMIZE,
+
+ /**
+ * Identifies the close button.
+ *
+ * @see Stage#close()
+ */
+ CLOSE
+}
--- a/modules/javafx.graphics/src/main/java/javafx/scene/layout/HeaderDragType.java
+++ b/modules/javafx.graphics/src/main/java/javafx/scene/layout/HeaderDragType.java
+
+/**
+ * Specifies whether a node is a draggable part of a {@link HeaderBar}.
+ *
+ * @since 25
+ * @deprecated This is a preview feature which may be changed or removed in a future release.
+ * @see HeaderBar#setDragType(Node, HeaderDragType)
+ */
+@Deprecated(since = "25")
+public enum HeaderDragType {
+
+ /**
+ * The node is not a draggable part of the {@code HeaderBar}.
+ *
+ * If the node inherits {@link #DRAGGABLE_SUBTREE} from its parent, the inheritance stops and
+ * descendants of the node will not inherit {@code DRAGGABLE_SUBTREE}.
+ */
+ NONE,
+
+ /**
+ * The node is a draggable part of the {@code HeaderBar}.
+ *
+ * This drag type does not apply to descendants of the node. However, it does not stop an inherited
+ * {@link #DRAGGABLE_SUBTREE} drag type from being inherited by descendants of the node.
+ */
+ DRAGGABLE,
+
+ /**
+ * The node and its descendants are a draggable part of the {@code HeaderBar}.
+ *
+ * This drag type is inherited by descendants of the node until a descendant specifies {@link #NONE}.
+ */
+ DRAGGABLE_SUBTREE
+}
--- a/modules/javafx.graphics/src/main/java/javafx/stage/StageStyle.java
+++ b/modules/javafx.graphics/src/main/java/javafx/stage/StageStyle.java
@@ -74,6 +82,60 @@
* NOTE: To see the effect, the {@code Scene} covering the {@code Stage} should have {@code Color.TRANSPARENT}
* @since JavaFX 8.0
*/
- UNIFIED
+ UNIFIED,
+
+ /**
+ * Defines a {@code Stage} style in which the client area is extended into the header bar area, removing
+ * the separation between the two areas and allowing applications to place scene graph nodes in the header
+ * bar area of the stage.
+ *
+ * This is a conditional feature, to check if it is supported see {@link Platform#isSupported(ConditionalFeature)}.
+ * If the feature is not supported by the platform, this style downgrades to {@link StageStyle#DECORATED}.
+ *
+ * Usage
+ * An extended window has the default header buttons (iconify, maximize, close), but no system-provided
+ * draggable header bar. Applications need to provide their own header bar by placing a {@link HeaderBar}
+ * control in the scene graph. The {@code HeaderBar} control should be positioned at the top of the window
+ * and its width should extend the entire width of the window, as otherwise the layout of the default window
+ * buttons and the header bar content might not be aligned correctly. Usually, {@code HeaderBar} is combined
+ * with a {@link BorderPane} root container:
+ * {@code
+ * public class MyApp extends Application {
+ * @Override
+ * public void start(Stage stage) {
+ * var headerBar = new HeaderBar();
+ * var root = new BorderPane();
+ * root.setTop(headerBar);
+ *
+ * stage.setScene(new Scene(root));
+ * stage.initStyle(StageStyle.EXTENDED);
+ * stage.show();
+ * }
+ * }
+ * }
+ *
+ * Color scheme
+ * The color scheme of the default header buttons is automatically adjusted to remain easily recognizable
+ * by inspecting the {@link Scene#fillProperty() Scene.fill} property to gauge the brightness of the user
+ * interface. Applications should set the scene fill to a color that matches the user interface of the header
+ * bar area, even if the scene fill is not visible because it is obscured by other controls.
+ *
+ * Custom header buttons
+ * If more control over the header buttons is desired, applications can opt out of the default header buttons
+ * by setting {@link HeaderBar#setPrefButtonHeight(Stage, double)} to zero and providing custom header buttons
+ * instead. Any JavaFX control can be used as a custom header button by setting its semantic type with the
+ * {@link HeaderBar#setButtonType(Node, HeaderButtonType)} method.
+ *
+ * Title text
+ * An extended stage has no title text. Applications that require title text need to provide their own
+ * implementation by placing a {@code Label} or a similar control in the custom header bar.
+ * Note that the value of {@link Stage#titleProperty()} may still be used by the platform, for example
+ * in the title of miniaturized preview windows.
+ *
+ * @since 25
+ * @deprecated This is a preview feature which may be changed or removed in a future release.
+ */
+ @Deprecated(since = "25")
+ EXTENDED
}