class NotificationController implements Initializable {

    private static final int ENTER_SPEED = 350;
    private static final int EXIT_SPEED = 350;
    private static final int ENTER_Y = 100;

    private static final String NOTIFICATION_FXML = "/fxml/Notification.fxml";
    private static final Duration TIMER = Duration.seconds(10);
    
    private final String message;
    private final Icon icon;
    private final Palette palette;
    private final Runnable onClose;
    private final AtomicBoolean destroyed;
    
    @FXML private Label notification;
    
    private NotificationController(
        final String message, 
        final Icon icon,
        final Palette palette, 
        final Runnable onClose
    ) {
        this.message = requireNonNull(message);
        this.icon    = requireNonNull(icon);
        this.palette = requireNonNull(palette);
        this.onClose = requireNonNull(onClose);
        
        this.destroyed = new AtomicBoolean(false);
    }

    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        notification.setText(message);
        notification.setGraphic(icon.view());
        notification.getStyleClass().add(palette.name().toLowerCase());
    }
    
    @FXML public void close() {
        if (destroyed.compareAndSet(false, true)) {
            onClose.run();
            remove(notification);
        }
    }
    
    private void fadeAway() {
        final FadeTransition fade = new FadeTransition(millis(EXIT_SPEED), notification);
        fade.setFromValue(1);
        fade.setToValue(0);

        final TranslateTransition trans = new TranslateTransition(millis(EXIT_SPEED), notification);
        trans.setFromY(0);
        trans.setToY(ENTER_Y);

        final SequentialTransition seq = new SequentialTransition(fade, trans);
        seq.setOnFinished(ev -> {
            if (destroyed.compareAndSet(false, true)) {
                remove(notification);
            }
        });
        seq.play();
    }

    static void showNotification(FlowPane area, String message, Icon icon, Palette palette, Runnable onClose) {

        final FXMLLoader loader = new FXMLLoader(NotificationController.class.getResource(NOTIFICATION_FXML));
        final AtomicReference<NotificationController> ref = new AtomicReference<>();
        loader.setControllerFactory(clazz -> {
            ref.set(new NotificationController(message, icon, palette, onClose));
            return ref.get();
        });
        final Node notification;
        
        try {
            notification = loader.load();
        } catch (final IOException ex) {
            throw new SpeedmentToolException(
                "Failed to load FXML-file: '" + NOTIFICATION_FXML + "'.", ex
            );
        }
        
        notification.setOpacity(0);
        notification.setLayoutX(area.getWidth());
        notification.setLayoutY(area.getHeight());
        
        final FadeTransition fade = new FadeTransition(millis(ENTER_SPEED), notification);
        fade.setFromValue(0);
        fade.setToValue(1);

        runLater(() -> {
            childrenOf(area).add(notification);
            fade.play();

            final Timeline timeline = new Timeline(new KeyFrame(
                TIMER, ev -> ref.get().fadeAway()
            ));
            timeline.play();
        });
    }
    
    private static void remove(Node node) {
        siblingsOf(node).remove(node);
    }
    
    private static ObservableList<Node> siblingsOf(Node node) {
        final Parent parent = node.getParent();
        
        if (parent == null) {
            throw new NullPointerException(
                "Can't delete node from 'null' parent."
            );
        }
        
        return childrenOf(parent);
    }
    
    private static ObservableList<Node> childrenOf(Node parent) {<FILL_FUNCTION_BODY>}
}

        final Method getChildren;
        try {
            getChildren = parent.getClass().getMethod("getChildren");
        } catch (final NoSuchMethodException | SecurityException ex) {
            throw new SpeedmentToolException(
                "Could not find public method 'getChildren()' in class '" + 
                parent.getClass() + "'.", ex
            );
        }
        
        try {
            @SuppressWarnings("unchecked")
            final ObservableList<Node> siblings = (ObservableList<Node>) getChildren.invoke(parent);
            return siblings;
        } catch (final IllegalAccessException 
                     | IllegalArgumentException 
                     | InvocationTargetException 
                     | ClassCastException ex) {
            throw new SpeedmentToolException(
                "Error executing 'getChildren()' in class '" + 
                parent.getClass() + "'.", ex
            );
        }
    
<no_super_class>