Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8261460

Incorrect CSS applied to ContextMenu on DialogPane

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • jfx17
    • jfx11, 8, jfx15
    • javafx
    • None

        Both DialogPane and ContextMenu have a child node with a style-class `graphic-container`. This leads to a corner case where an unwanted style is applied to ContextMenu when it is shown on a DialogPane.

        To reproduce:

        * Show a Dialog without a Header
        * Show a ContextMenu with a MenuItem that has a Graphic Node
        * Observe the alignment and spacing of the MenuItem Graphic Node relative to the MenuItem Label text

        The same can be reproduced by running the following sample:

        import javafx.application.Application;
        import javafx.geometry.Pos;
        import javafx.scene.Scene;
        import javafx.scene.control.*;
        import javafx.scene.image.Image;
        import javafx.scene.image.ImageView;
        import javafx.scene.layout.FlowPane;
        import javafx.stage.Stage;

        import java.io.IOException;
        import java.nio.file.Files;
        import java.nio.file.Path;

        public class DialogPaneContextMenuCSSBug extends Application {

            public static final Image IMAGE = new Image("https://i.imgur.com/qE8IbBz.png");

            @Override
            public void start(final Stage primaryStage) {
                primaryStage.setTitle("JavaFX");

                final Button btnHeader = new Button("Header Dialog");
                btnHeader.setOnAction(e -> createDialog(primaryStage, DialogPaneType.HEADER_NODE).showAndWait());

                final Button btnHeaderText = new Button("Header Text Dialog");
                btnHeaderText.setOnAction(e -> createDialog(primaryStage, DialogPaneType.HEADER_TEXT).showAndWait());

                final Button btnNoHeader = new Button("No Header Dialog");
                btnNoHeader.setOnAction(e -> createDialog(primaryStage, DialogPaneType.NONE).showAndWait());

                FlowPane root = new FlowPane(btnHeader, btnHeaderText, btnNoHeader);
                root.setHgap(10);
                root.setVgap(10);
                root.setAlignment(Pos.CENTER);
                final Scene scene = new Scene(root, 300, 250);
                primaryStage.setScene(scene);
                // scene.getStylesheets().add(createStyleSheet());
                primaryStage.show();
            }

            private ContextMenu createContextMenu() {
                final MenuItem menuItem = new MenuItem("Menu Item Text", new ImageView(IMAGE));
                return new ContextMenu(menuItem);
            }

            private Dialog<String> createDialog(final Stage primaryStage, DialogPaneType dialogPaneType) {
                final Dialog<String> dialog = new Dialog<>();
                dialog.initOwner(primaryStage);
                final DialogPane dialogPane = new DialogPane();
                dialog.setOnCloseRequest(e -> dialog.close());

                final Label label = new Label("Right click me for context menu");
                final ContextMenu contextMenu = createContextMenu();
                label.setContextMenu(contextMenu);

                switch (dialogPaneType) {
                    case HEADER_NODE -> dialogPane.setHeader(new Label("Header"));
                    case HEADER_TEXT -> dialogPane.setHeaderText("Header Text");
                }
                dialogPane.setGraphic(new ImageView(IMAGE));
                dialogPane.setContent(label);
                dialogPane.getButtonTypes().add(ButtonType.CANCEL);
                dialog.setDialogPane(dialogPane);

                return dialog;
            }

            private enum DialogPaneType {
                HEADER_NODE,
                HEADER_TEXT,
                NONE
            }

            /** */
            /* Stylesheet related code */
            /* */
            private String createStyleSheet() {
                Path tempFile = null;
                try {
                    tempFile = Files.createTempFile("", "");
                    Files.writeString(tempFile, STYLE_SHEET);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return tempFile.toUri().toString();
            }

            private static String STYLE_SHEET =
                    """
                    .dialog-pane:no-header .graphic-container {
                        -fx-padding: 0em 0.333em 0em 0em;
                    }
                
                    .dialog-pane:no-header > * > .graphic-container {
                        -fx-padding: 0.833em 0 0 0.833em;
                    }
                    """;
        }

        Fix
        -------
        The following style in modena.css should be updated:

        ```
        .dialog-pane:no-header .graphic-container {
            -fx-padding: 0em 0.333em 0em 0em;
        }
        ```

        to

        ```
        .dialog-pane:no-header > * > .graphic-container {
            -fx-padding: 0em 0.333em 0em 0em;
        }
        ```

        Workaround
        -----------------
        The above CSS should be added to Application

              abagarwal Abhinay Agarwal
              abagarwal Abhinay Agarwal
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated:
                Resolved: