11/*
2- * Copyright (c) 2014, 2024 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2014, 2025 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
3131import java .util .Map ;
3232import java .util .WeakHashMap ;
3333
34+ import com .sun .javafx .PreviewFeature ;
35+ import com .sun .javafx .css .StyleManager ;
3436import com .sun .javafx .scene .control .skin .Utils ;
3537import com .sun .javafx .scene .control .skin .resources .ControlResources ;
3638import javafx .beans .DefaultProperty ;
5153import javafx .css .StyleableObjectProperty ;
5254import javafx .css .StyleableProperty ;
5355import javafx .css .StyleableStringProperty ;
56+ import javafx .css .converter .StringConverter ;
5457import javafx .event .ActionEvent ;
58+ import javafx .geometry .HPos ;
5559import javafx .geometry .Pos ;
60+ import javafx .geometry .VPos ;
5661import javafx .scene .AccessibleRole ;
5762import javafx .scene .Node ;
5863import javafx .scene .control .ButtonBar .ButtonData ;
5964import javafx .scene .image .Image ;
6065import javafx .scene .image .ImageView ;
6166import javafx .scene .layout .ColumnConstraints ;
6267import javafx .scene .layout .GridPane ;
68+ import javafx .scene .layout .HeaderBar ;
6369import javafx .scene .layout .Pane ;
6470import javafx .scene .layout .Priority ;
6571import javafx .scene .layout .Region ;
6672import javafx .scene .layout .StackPane ;
67-
68- import com .sun .javafx .css .StyleManager ;
69- import javafx .css .converter .StringConverter ;
73+ import javafx .stage .StageStyle ;
7074
7175/**
7276 * DialogPane should be considered to be the root node displayed within a
@@ -430,6 +434,79 @@ public CssMetaData<DialogPane,String> getCssMetaData() {
430434 return imageUrl ;
431435 }
432436
437+ // --- header bar
438+ private ObjectProperty <HeaderBar > headerBar ;
439+
440+ /**
441+ * Specifies the {@link HeaderBar} for the dialog. The {@code HeaderBar} will be placed at the
442+ * top of the dialog window, and extend the entire width of the window. This property will only
443+ * be used if the dialog window is configured with the {@link StageStyle#EXTENDED} style; it has
444+ * no effect for other styles.
445+ *
446+ * @return the {@code headerBar} property
447+ * @defaultValue {@code null}
448+ * @since 26
449+ * @deprecated This is a preview feature which may be changed or removed in a future release.
450+ */
451+ @ Deprecated (since = "26" )
452+ public final ObjectProperty <HeaderBar > headerBarProperty () {
453+ if (headerBar == null ) {
454+ PreviewFeature .HEADER_BAR .checkEnabled ();
455+ headerBar = new SimpleObjectProperty <>(this , "headerBar" ) {
456+ WeakReference <HeaderBar > wref = new WeakReference <>(null );
457+
458+ @ Override
459+ protected void invalidated () {
460+ HeaderBar oldValue = wref .get ();
461+ if (oldValue != null ) {
462+ getChildren ().remove (oldValue );
463+ }
464+
465+ HeaderBar newValue = get ();
466+ if (newValue != null ) {
467+ getChildren ().add (newValue );
468+ }
469+
470+ wref = new WeakReference <>(newValue );
471+ }
472+ };
473+ }
474+
475+ return headerBar ;
476+ }
477+
478+ /**
479+ * Gets the value of the {@link #headerBarProperty() headerBar} property.
480+ *
481+ * @return the {@code HeaderBar}
482+ * @since 26
483+ * @deprecated This is a preview feature which may be changed or removed in a future release.
484+ */
485+ @ Deprecated (since = "26" )
486+ public final HeaderBar getHeaderBar () {
487+ PreviewFeature .HEADER_BAR .checkEnabled ();
488+ return headerBar != null ? headerBar .get () : null ;
489+ }
490+
491+ /**
492+ * Sets the value of the {@link #headerBarProperty() headerBar} property.
493+ *
494+ * @param value the new value
495+ * @since 26
496+ * @deprecated This is a preview feature which may be changed or removed in a future release.
497+ */
498+ @ Deprecated (since = "26" )
499+ public final void setHeaderBar (HeaderBar value ) {
500+ PreviewFeature .HEADER_BAR .checkEnabled ();
501+ if (headerBar != null || value != null ) {
502+ headerBarProperty ().set (value );
503+ }
504+ }
505+
506+ // This method skips the preview feature check for internal use and can be removed when HeaderBar is finalized.
507+ private HeaderBar getHeaderBarInternal () {
508+ return headerBar != null ? headerBar .get () : null ;
509+ }
433510
434511 // --- header
435512 private final ObjectProperty <Node > header = new SimpleObjectProperty <>(null ) {
@@ -878,11 +955,15 @@ protected Node createDetailsButton() {
878955 final Node content = getActualContent ();
879956 final Node graphic = getActualGraphic ();
880957 final Node expandableContent = getExpandableContent ();
958+ final HeaderBar headerBar = getHeaderBarInternal ();
881959
882960 final double graphicPrefWidth = hasHeader || graphic == null ? 0 : graphic .prefWidth (-1 );
883961 final double headerPrefHeight = hasHeader ? header .prefHeight (w ) : 0 ;
884962 final double buttonBarPrefHeight = buttonBar == null ? 0 : buttonBar .prefHeight (w );
885963 final double graphicPrefHeight = hasHeader || graphic == null ? 0 : graphic .prefHeight (-1 );
964+ final double headerBarPrefHeight = headerBar != null
965+ ? Utils .boundedSize (headerBar .prefHeight (w ), headerBar .minHeight (w ), headerBar .maxHeight (w ))
966+ : 0 ;
886967
887968 final double expandableContentPrefHeight ;
888969 final double contentAreaHeight ;
@@ -894,16 +975,20 @@ protected Node createDetailsButton() {
894975 // precedence goes to content and then expandable content
895976 contentAreaHeight = isExpanded () ? content .prefHeight (availableContentWidth ) : 0 ;
896977 contentAndGraphicHeight = hasHeader ? contentAreaHeight : Math .max (graphicPrefHeight , contentAreaHeight );
897- expandableContentPrefHeight = h - (headerPrefHeight + contentAndGraphicHeight + buttonBarPrefHeight );
978+ expandableContentPrefHeight = h - (headerBarPrefHeight + headerPrefHeight + contentAndGraphicHeight + buttonBarPrefHeight );
898979 } else {
899980 // content gets the lowest precedence
900981 expandableContentPrefHeight = isExpanded () ? expandableContent .prefHeight (w ) : 0 ;
901- contentAreaHeight = h - (headerPrefHeight + expandableContentPrefHeight + buttonBarPrefHeight );
982+ contentAreaHeight = h - (headerBarPrefHeight + headerPrefHeight + expandableContentPrefHeight + buttonBarPrefHeight );
902983 contentAndGraphicHeight = hasHeader ? contentAreaHeight : Math .max (graphicPrefHeight , contentAreaHeight );
903984 }
904985
986+ if (headerBar != null ) {
987+ layoutInArea (headerBar , 0 , 0 , w , headerBarPrefHeight , 0 , HPos .LEFT , VPos .TOP );
988+ }
989+
905990 double x = leftPadding ;
906- double y = topPadding ;
991+ double y = topPadding + headerBarPrefHeight ;
907992
908993 if (! hasHeader ) {
909994 if (graphic != null ) {
@@ -933,6 +1018,7 @@ protected Node createDetailsButton() {
9331018
9341019 /** {@inheritDoc} */
9351020 @ Override protected double computeMinWidth (double height ) {
1021+ double headerBarMinWidth = getHeaderBarInternal () instanceof HeaderBar hb ? hb .minWidth (height ) : 0 ;
9361022 double headerMinWidth = hasHeader () ? getActualHeader ().minWidth (height ) + 10 : 0 ;
9371023 double contentMinWidth = getActualContent ().minWidth (height );
9381024 double buttonBarMinWidth = buttonBar == null ? 0 : buttonBar .minWidth (height );
@@ -949,13 +1035,14 @@ protected Node createDetailsButton() {
9491035 Math .max (Math .max (headerMinWidth , expandableContentMinWidth ), Math .max (contentMinWidth , buttonBarMinWidth )) +
9501036 snappedRightInset ();
9511037
952- return snapSizeX (minWidth );
1038+ return snapSizeX (Math . max ( minWidth , headerBarMinWidth ) );
9531039 }
9541040
9551041 /** {@inheritDoc} */
9561042 @ Override protected double computeMinHeight (double width ) {
9571043 final boolean hasHeader = hasHeader ();
9581044
1045+ double headerBarMinHeight = getHeaderBarInternal () instanceof HeaderBar hb ? hb .minHeight (width ) : 0 ;
9591046 double headerMinHeight = hasHeader ? getActualHeader ().minHeight (width ) : 0 ;
9601047 double buttonBarMinHeight = buttonBar == null ? 0 : buttonBar .minHeight (width );
9611048
@@ -976,6 +1063,7 @@ protected Node createDetailsButton() {
9761063 }
9771064
9781065 double minHeight = snappedTopInset () +
1066+ headerBarMinHeight +
9791067 headerMinHeight +
9801068 Math .max (graphicMinHeight , contentMinHeight ) +
9811069 expandableContentMinHeight +
@@ -991,6 +1079,8 @@ protected Node createDetailsButton() {
9911079 double contentPrefWidth = getActualContent ().prefWidth (height );
9921080 double buttonBarPrefWidth = buttonBar == null ? 0 : buttonBar .prefWidth (height );
9931081 double graphicPrefWidth = getActualGraphic ().prefWidth (height );
1082+ double headerBarPrefWidth = getHeaderBarInternal () instanceof HeaderBar hb
1083+ ? Utils .boundedSize (hb .prefWidth (height ), hb .minWidth (height ), hb .maxWidth (height )) : 0 ;
9941084
9951085 double expandableContentPrefWidth = 0 ;
9961086 final Node expandableContent = getExpandableContent ();
@@ -1003,7 +1093,7 @@ protected Node createDetailsButton() {
10031093 Math .max (Math .max (headerPrefWidth , expandableContentPrefWidth ), Math .max (contentPrefWidth , buttonBarPrefWidth )) +
10041094 snappedRightInset ();
10051095
1006- return snapSizeX (prefWidth );
1096+ return snapSizeX (Math . max ( prefWidth , headerBarPrefWidth ) );
10071097 }
10081098
10091099 /** {@inheritDoc} */
@@ -1012,6 +1102,8 @@ protected Node createDetailsButton() {
10121102
10131103 double headerPrefHeight = hasHeader ? getActualHeader ().prefHeight (width ) : 0 ;
10141104 double buttonBarPrefHeight = buttonBar == null ? 0 : buttonBar .prefHeight (width );
1105+ double headerBarPrefHeight = getHeaderBarInternal () instanceof HeaderBar hb
1106+ ? Utils .boundedSize (hb .prefHeight (width ), hb .minHeight (width ), hb .maxHeight (width )) : 0 ;
10151107
10161108 Node graphic = getActualGraphic ();
10171109 double graphicPrefWidth = hasHeader ? 0 : graphic .prefWidth (-1 );
@@ -1029,6 +1121,7 @@ protected Node createDetailsButton() {
10291121 }
10301122
10311123 double prefHeight = snappedTopInset () +
1124+ headerBarPrefHeight +
10321125 headerPrefHeight +
10331126 Math .max (graphicPrefHeight , contentPrefHeight ) +
10341127 expandableContentPrefHeight +
0 commit comments