All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jfoenix.controls.JFXDrawer Maven / Gradle / Ivy

There is a newer version: 9.0.10
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package com.jfoenix.controls;

import com.jfoenix.controls.events.JFXDrawerEvent;
import com.jfoenix.transitions.JFXAnimationTimer;
import com.jfoenix.transitions.JFXKeyFrame;
import com.jfoenix.transitions.JFXKeyValue;
import javafx.animation.Interpolator;
import javafx.animation.PauseTransition;
import javafx.animation.Transition;
import javafx.beans.binding.Bindings;
import javafx.beans.property.*;
import javafx.beans.value.ChangeListener;
import javafx.collections.ObservableList;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.util.Callback;
import javafx.util.Duration;

import java.util.ArrayList;

/**
 * JFXDrawer is material design implementation of drawer.
 * the drawer has two main nodes, the content and side pane.
 * 
    *
  • content pane: is a stack pane that holds the nodes inside the drawer
  • *
  • side pane: is a stack pane that holds the nodes inside the drawer side area (Drawable node)
  • *
* * @author Shadi Shaheen * @version 1.0 * @since 2016-03-09 */ public class JFXDrawer extends StackPane { /** * Defines the directions that a {@link JFXDrawer} can originate from. */ public enum DrawerDirection { LEFT(1), RIGHT(-1), TOP(1), BOTTOM(-1); private double numVal; DrawerDirection(double numVal) { this.numVal = numVal; } public double doubleValue() { return numVal; } } private StackPane overlayPane = new StackPane(); StackPane sidePane = new StackPane(); private StackPane content = new StackPane(); private Transition drawerTransition; private Transition partialTransition; private Duration holdTime = Duration.seconds(0.2); private PauseTransition holdTimer = new PauseTransition(holdTime); private double initOffset = 30; private DoubleProperty initTranslate = new SimpleDoubleProperty(); private BooleanProperty overLayVisible = new SimpleBooleanProperty(true); private double activeOffset = 20; private double startMouse = -1; private double startTranslate = -1; private double startSize = -1; private DoubleProperty translateProperty = sidePane.translateXProperty(); private boolean resizable = false; private boolean openCalled = false; private boolean closeCalled = true; private DoubleProperty defaultSizeProperty = new SimpleDoubleProperty(); private ObjectProperty maxSizeProperty = new SimpleObjectProperty<>(sidePane.maxWidthProperty()); private ObjectProperty minSizeProperty = new SimpleObjectProperty<>(sidePane.minWidthProperty()); private ObjectProperty prefSizeProperty = new SimpleObjectProperty<>(sidePane.prefWidthProperty()); private ObjectProperty sizeProperty = new SimpleObjectProperty<>(sidePane.widthProperty()); private ObjectProperty parentSizeProperty = new SimpleObjectProperty<>(); private ObjectProperty boundedNode = new SimpleObjectProperty<>(); private SimpleObjectProperty directionProperty = new SimpleObjectProperty<>( DrawerDirection.LEFT); /*************************************************************************** * * * Animations * * * **************************************************************************/ double translateTo = 0; private double tempDrawerSize = getDefaultDrawerSize(); private JFXAnimationTimer translateTimer = new JFXAnimationTimer( new JFXKeyFrame(Duration.millis(420), JFXKeyValue.builder() .setTargetSupplier(() -> translateProperty) .setEndValueSupplier(() -> translateTo) .setInterpolator(Interpolator.EASE_BOTH).build()), new JFXKeyFrame(Duration.millis(420), JFXKeyValue.builder() .setTargetSupplier(() -> prefSizeProperty.get()) .setEndValueSupplier(() -> getDefaultDrawerSize()) .setAnimateCondition(() -> translateTo == initTranslate.get()) .setInterpolator(Interpolator.EASE_BOTH).build()), new JFXKeyFrame(Duration.millis(420), JFXKeyValue.builder() .setTargetSupplier(() -> maxSizeProperty.get()) .setEndValueSupplier(() -> getDefaultDrawerSize()) .setAnimateCondition(() -> translateTo == initTranslate.get()) .setInterpolator(Interpolator.EASE_BOTH).build()), new JFXKeyFrame(Duration.millis(420), JFXKeyValue.builder() .setTargetSupplier(() -> prefSizeProperty.get()) .setEndValueSupplier(() -> tempDrawerSize) .setAnimateCondition(() -> translateTo == 0 && tempDrawerSize > getDefaultDrawerSize()) .setInterpolator(Interpolator.EASE_BOTH).build()), new JFXKeyFrame(Duration.millis(420), JFXKeyValue.builder() .setTargetSupplier(() -> maxSizeProperty.get()) .setEndValueSupplier(() -> tempDrawerSize) .setAnimateCondition(() -> translateTo == 0 && tempDrawerSize > getDefaultDrawerSize()) .setInterpolator(Interpolator.EASE_BOTH).build()) ); /** * creates empty drawer node */ public JFXDrawer() { initialize(); overlayPane.setBackground(new Background(new BackgroundFill(Color.rgb(0, 0, 0, 0.1), CornerRadii.EMPTY, Insets.EMPTY))); overlayPane.getStyleClass().add("jfx-drawer-overlay-pane"); overlayPane.setOpacity(0); overlayPane.setMouseTransparent(true); sidePane.getStyleClass().add("jfx-drawer-side-pane"); sidePane.setBackground(new Background(new BackgroundFill(Color.rgb(255, 255, 255, 1), CornerRadii.EMPTY, Insets.EMPTY))); sidePane.setPickOnBounds(false); translateTimer.setCacheNodes(sidePane); // add listeners initListeners(); // init size value setDefaultDrawerSize(100); this.getChildren().addAll(overlayPane, sidePane); } private void initialize() { this.getStyleClass().add(DEFAULT_STYLE_CLASS); } private void initListeners() { updateDirection(directionProperty.get()); initTranslate.bind(Bindings.createDoubleBinding(() -> -1 * directionProperty.get().doubleValue() * defaultSizeProperty.getValue() - initOffset * directionProperty.get().doubleValue(), defaultSizeProperty, directionProperty)); // add listeners to update drawer properties overLayVisibleProperty().addListener(observable -> { final boolean overLayVisible = isOverLayVisible(); overlayPane.setStyle(!overLayVisible ? "-fx-background-color : transparent;" : ""); overlayPane.setPickOnBounds(overLayVisible); }); directionProperty.addListener(observable -> updateDirection(directionProperty.get())); initTranslate.addListener(observable -> updateDrawerAnimation(initTranslate.get())); // mouse drag handler translateProperty.addListener(observable -> overlayPane.setOpacity(1 - translateProperty.doubleValue() / initTranslate.get())); // add opening/closing action listeners translateProperty.addListener((o, oldVal, newVal) -> { if (!openCalled && closeCalled && directionProperty.get().doubleValue() * newVal.doubleValue() > directionProperty.get().doubleValue() * initTranslate.get() / 2) { openCalled = true; closeCalled = false; fireEvent(new JFXDrawerEvent(JFXDrawerEvent.OPENING)); } }); translateProperty.addListener((o, oldVal, newVal) -> { if (openCalled && !closeCalled && directionProperty.get().doubleValue() * newVal.doubleValue() < directionProperty.get().doubleValue() * initTranslate.get() / 2) { closeCalled = true; openCalled = false; fireEvent(new JFXDrawerEvent(JFXDrawerEvent.CLOSING)); } }); overlayPane.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> close()); sidePane.addEventHandler(MouseEvent.MOUSE_DRAGGED, mouseDragHandler); sidePane.addEventHandler(MouseEvent.MOUSE_RELEASED, mouseReleasedHandler); sidePane.addEventHandler(MouseEvent.MOUSE_PRESSED, mousePressedHandler); // content listener for mouse hold on a side this.content.addEventHandler(MouseEvent.MOUSE_PRESSED, (e) -> { if (!e.isConsumed()) { double size = 0; long valid = 0; for (int i = 0; i < callBacks.size(); i++) { if (!callBacks.get(i).call(null)) { valid++; } } if (directionProperty.get() == DrawerDirection.RIGHT) { size = content.getWidth(); } else if (directionProperty.get() == DrawerDirection.BOTTOM) { size = content.getHeight(); } double eventPoint = 0; if (directionProperty.get() == DrawerDirection.RIGHT || directionProperty.get() == DrawerDirection.LEFT) { eventPoint = e.getX(); } else { eventPoint = e.getY(); } if (size + directionProperty.get().doubleValue() * eventPoint < activeOffset && (content.getCursor() == Cursor.DEFAULT || content.getCursor() == null) && valid == 0) { holdTimer.play(); e.consume(); } } }); this.content.addEventHandler(MouseEvent.MOUSE_RELEASED, (e) -> { holdTimer.stop(); this.content.removeEventFilter(MouseEvent.MOUSE_DRAGGED, mouseDragHandler); }); holdTimer.setOnFinished(e -> { translateTo = initTranslate.get() + initOffset * directionProperty.get().doubleValue() + activeOffset * directionProperty.get().doubleValue(); overlayPane.setMouseTransparent(!isOverLayVisible()); translateTimer.setOnFinished(null); translateTimer.start(); }); } ChangeListener widthListener = (o, oldVal, newVal) -> { if (newVal != null && newVal instanceof Region) { parentSizeProperty.set(((Region) newVal).widthProperty()); } }; ChangeListener heightListener = (o, oldVal, newVal) -> { if (newVal != null && newVal instanceof Region) { parentSizeProperty.set(((Region) newVal).heightProperty()); } }; ChangeListener sceneWidthListener = (o, oldVal, newVal) -> { if (newVal != null && this.getParent() == null) { parentSizeProperty.set(newVal.widthProperty()); } }; ChangeListener sceneHeightListener = (o, oldVal, newVal) -> { if (newVal != null && this.getParent() == null) { parentSizeProperty.set(newVal.heightProperty()); } }; /** * This method will change the drawer behavior according to the argument direction. * * @param dir - The direction that the drawer will enter the screen from. */ private void updateDirection(DrawerDirection dir) { maxSizeProperty.get().set(-1); prefSizeProperty.get().set(-1); if (dir == DrawerDirection.LEFT) { // change the pane position StackPane.setAlignment(sidePane, Pos.CENTER_LEFT); // reset old translation translateProperty.set(0); // set the new translation property translateProperty = sidePane.translateXProperty(); // change the size property maxSizeProperty.set(sidePane.maxWidthProperty()); minSizeProperty.set(sidePane.minWidthProperty()); prefSizeProperty.set(sidePane.prefWidthProperty()); sizeProperty.set(sidePane.widthProperty()); this.boundedNodeProperty().removeListener(heightListener); this.boundedNodeProperty().addListener(widthListener); if (getBoundedNode() == null) { this.boundedNodeProperty().bind(this.parentProperty()); } this.sceneProperty().removeListener(sceneHeightListener); this.sceneProperty().removeListener(sceneWidthListener); this.sceneProperty().addListener(sceneWidthListener); } else if (dir == DrawerDirection.RIGHT) { StackPane.setAlignment(sidePane, Pos.CENTER_RIGHT); translateProperty.set(0); translateProperty = sidePane.translateXProperty(); maxSizeProperty.set(sidePane.maxWidthProperty()); minSizeProperty.set(sidePane.minWidthProperty()); prefSizeProperty.set(sidePane.prefWidthProperty()); sizeProperty.set(sidePane.widthProperty()); this.boundedNodeProperty().removeListener(heightListener); this.boundedNodeProperty().addListener(widthListener); if (getBoundedNode() == null) { this.boundedNodeProperty().bind(this.parentProperty()); } this.sceneProperty().removeListener(sceneHeightListener); this.sceneProperty().removeListener(sceneWidthListener); this.sceneProperty().addListener(sceneWidthListener); } else if (dir == DrawerDirection.TOP) { StackPane.setAlignment(sidePane, Pos.TOP_CENTER); translateProperty.set(0); translateProperty = sidePane.translateYProperty(); maxSizeProperty.set(sidePane.maxHeightProperty()); minSizeProperty.set(sidePane.minHeightProperty()); prefSizeProperty.set(sidePane.prefHeightProperty()); sizeProperty.set(sidePane.heightProperty()); this.boundedNodeProperty().removeListener(widthListener); this.boundedNodeProperty().addListener(heightListener); if (getBoundedNode() == null) { this.boundedNodeProperty().bind(this.parentProperty()); } this.sceneProperty().removeListener(sceneHeightListener); this.sceneProperty().removeListener(sceneWidthListener); this.sceneProperty().addListener(sceneHeightListener); } else if (dir == DrawerDirection.BOTTOM) { StackPane.setAlignment(sidePane, Pos.BOTTOM_CENTER); translateProperty.set(0); translateProperty = sidePane.translateYProperty(); maxSizeProperty.set(sidePane.maxHeightProperty()); minSizeProperty.set(sidePane.minHeightProperty()); prefSizeProperty.set(sidePane.prefHeightProperty()); sizeProperty.set(sidePane.heightProperty()); this.boundedNodeProperty().removeListener(widthListener); this.boundedNodeProperty().addListener(heightListener); if (getBoundedNode() == null) { this.boundedNodeProperty().bind(this.parentProperty()); } this.sceneProperty().removeListener(sceneHeightListener); this.sceneProperty().removeListener(sceneWidthListener); this.sceneProperty().addListener(sceneHeightListener); } setDefaultDrawerSize(defaultSizeProperty.get()); updateDrawerAnimation(initTranslate.get()); } private void updateDrawerAnimation(double translation) { translateProperty.set(translation); translateTo = translation; } /*************************************************************************** * * * Public API * * * **************************************************************************/ private ArrayList> callBacks = new ArrayList<>(); /** * the callbacks are used to add conditions to allow * starting the drawer when holding on the side part of the content */ public void addInitDrawerCallback(Callback callBack) { callBacks.add(callBack); } /** * this method is only used in drawers stack component * * @param callback */ void bringToFront(Callback callback) { EventHandler eventFilter = Event::consume; final boolean bindSize = prefSizeProperty.get().isBound(); prefSizeProperty.get().unbind(); maxSizeProperty.get().unbind(); // disable mouse events this.addEventFilter(MouseEvent.ANY, eventFilter); Runnable onFinished = () -> { callback.call(null); translateTo = 0; translateTimer.setOnFinished(() -> { if (bindSize) { prefSizeProperty.get().bind(parentSizeProperty.get()); maxSizeProperty.get().bind(parentSizeProperty.get()); } // enable mouse events this.removeEventFilter(MouseEvent.ANY, eventFilter); }); translateTimer.start(); }; if (sizeProperty.get().get() > getDefaultDrawerSize()) { tempDrawerSize = sizeProperty.get().get(); } else { tempDrawerSize = getDefaultDrawerSize(); } translateTo = initTranslate.get(); translateTimer.setOnFinished(onFinished); translateTimer.start(); } /** * This indicates whether or not the drawer is completely shown. * * @return True if the drawer is totally visible and not transitioning, otherwise false. */ public boolean isShown() { return translateTo == 0 && !translateTimer.isRunning(); } /** * This indicates whether or not the drawer is in the process of being shown. * * @return True if the drawer is transitioning from closed to open, otherwise false. */ public boolean isShowing() { return translateTo == 0 && translateTimer.isRunning(); } /** * This indicates whether or not the drawer is in the process of being hidden. * * @return True if the drawer is transitioning from open to closed, otherwise false. */ public boolean isHiding() { return translateTo == initTranslate.get() && translateTimer.isRunning(); } /** * This indicates whether or not the drawer is completely hidden. * * @return True if the drawer is hidden and not in the process of transitioning, otherwise false. */ public boolean isHidden() { return translateTo == initTranslate.get() && !translateTimer.isRunning(); } /** * Toggles the drawer between open and closed. The drawer will be closed if it is shown or transitioning between * closed and open. Likewise, it will be opened if it is open or transitioning from open to closed. */ public void toggle(){ if(isShown() || isShowing()){ close(); }else{ open(); } } /** * Starts the animation to transition this drawer to open. */ public void open() { translateTo = 0; overlayPane.setMouseTransparent(!isOverLayVisible()); translateTimer.setOnFinished(() -> fireEvent(new JFXDrawerEvent(JFXDrawerEvent.OPENED))); translateTimer.reverseAndContinue(); } /** * Starts the animation to transition this drawer to closed. */ public void close() { // unbind properties as the drawer size might be bound to stage size maxSizeProperty.get().unbind(); prefSizeProperty.get().unbind(); if (sizeProperty.get().get() > getDefaultDrawerSize()) { tempDrawerSize = prefSizeProperty.get().get(); } else { tempDrawerSize = getDefaultDrawerSize(); } if(translateTo != initTranslate.get()){ translateTo = initTranslate.get(); translateTimer.reverseAndContinue(); } translateTimer.setOnFinished(() -> { overlayPane.setMouseTransparent(true); fireEvent(new JFXDrawerEvent(JFXDrawerEvent.CLOSED)); }); } /*************************************************************************** * * * Setters / Getters * * * **************************************************************************/ public ObservableList getSidePane() { return sidePane.getChildren(); } public void setSidePane(Node... sidePane) { this.sidePane.getChildren().setAll(sidePane); } public ObservableList getContent() { if (!getChildren().contains(this.content)) { getChildren().add(0, this.content); } return content.getChildren(); } public void setContent(Node... content) { this.content.getChildren().setAll(content); if (!getChildren().contains(this.content)) { getChildren().add(0, this.content); } } public double getDefaultDrawerSize() { return defaultSizeProperty.get(); } public void setDefaultDrawerSize(double drawerWidth) { defaultSizeProperty.set(drawerWidth); maxSizeProperty.get().set(drawerWidth); prefSizeProperty.get().set(drawerWidth); } public DrawerDirection getDirection() { return directionProperty.get(); } public SimpleObjectProperty directionProperty() { return directionProperty; } public void setDirection(DrawerDirection direction) { this.directionProperty.set(direction); } public final BooleanProperty overLayVisibleProperty() { return this.overLayVisible; } public final boolean isOverLayVisible() { return this.overLayVisibleProperty().get(); } public final void setOverLayVisible(final boolean overLayVisible) { this.overLayVisibleProperty().set(overLayVisible); } public boolean isResizableOnDrag() { return resizable; } public void setResizableOnDrag(boolean resizable) { this.resizable = resizable; } private final ObjectProperty boundedNodeProperty() { return this.boundedNode; } private final Node getBoundedNode() { return this.boundedNodeProperty().get(); } private final void setBoundedNode(final Node boundedNode) { this.boundedNodeProperty().unbind(); this.boundedNodeProperty().set(boundedNode); } /*************************************************************************** * * * Custom Events * * * **************************************************************************/ public EventHandler getOnDrawerClosed() { return onDrawerClosedProperty().get(); } public ObjectProperty> onDrawerClosedProperty() { return onDrawerClosed; } public void setOnDrawerClosed(EventHandler onDrawerClosed) { onDrawerClosedProperty().set(onDrawerClosed); } private ObjectProperty> onDrawerClosed = new ObjectPropertyBase>() { @Override protected void invalidated() { setEventHandler(JFXDrawerEvent.CLOSED, get()); } @Override public Object getBean() { return JFXDrawer.this; } @Override public String getName() { return "onClosed"; } }; public EventHandler getOnDrawerClosing() { return onDrawerClosing.get(); } public ObjectProperty> onDrawerClosingProperty() { return onDrawerClosing; } public void setOnDrawerClosing(EventHandler onDrawerClosing) { this.onDrawerClosing.set(onDrawerClosing); } private ObjectProperty> onDrawerClosing = new ObjectPropertyBase>() { @Override protected void invalidated() { setEventHandler(JFXDrawerEvent.CLOSING, get()); } @Override public Object getBean() { return JFXDrawer.this; } @Override public String getName() { return "onClosing"; } }; public EventHandler getOnDrawerOpened() { return onDrawerOpened.get(); } public ObjectProperty> onDrawerOpenedProperty() { return onDrawerOpened; } public void setOnDrawerOpened(EventHandler onDrawerOpened) { this.onDrawerOpened.set(onDrawerOpened); } private ObjectProperty> onDrawerOpened = new ObjectPropertyBase>() { @Override protected void invalidated() { setEventHandler(JFXDrawerEvent.OPENED, get()); } @Override public Object getBean() { return JFXDrawer.this; } @Override public String getName() { return "onOpened"; } }; public EventHandler getOnDrawerOpening() { return onDrawerOpening.get(); } public ObjectProperty> onDrawerOpeningProperty() { return onDrawerOpening; } public void setOnDrawerOpening(EventHandler onDrawerOpening) { this.onDrawerOpening.set(onDrawerOpening); } private ObjectProperty> onDrawerOpening = new ObjectPropertyBase>() { @Override protected void invalidated() { setEventHandler(JFXDrawerEvent.OPENING, get()); } @Override public Object getBean() { return JFXDrawer.this; } @Override public String getName() { return "onOpening"; } }; /*************************************************************************** * * * Action Handlers * * * **************************************************************************/ private EventHandler mouseDragHandler = (mouseEvent) -> { if (!mouseEvent.isConsumed()) { mouseEvent.consume(); double size = 0; Bounds sceneBounds = content.localToScene(content.getLayoutBounds()); if (directionProperty.get() == DrawerDirection.RIGHT) { size = sceneBounds.getMinX() + sceneBounds.getWidth(); } else if (directionProperty.get() == DrawerDirection.BOTTOM) { size = sceneBounds.getMinY() + sceneBounds.getHeight(); } if (startSize == -1) { startSize = sizeProperty.get().get(); } double eventPoint = 0; if (directionProperty.get() == DrawerDirection.RIGHT || directionProperty.get() == DrawerDirection.LEFT) { eventPoint = mouseEvent.getSceneX(); } else { eventPoint = mouseEvent.getSceneY(); } if (((size + (directionProperty.get().doubleValue() * eventPoint)) >= activeOffset) && (partialTransition != null)) { partialTransition = null; } else if (partialTransition == null) { double currentTranslate; if (startMouse < 0) { currentTranslate = initTranslate.get() + directionProperty.get().doubleValue() * initOffset + directionProperty.get().doubleValue() * (size + directionProperty.get().doubleValue() * eventPoint); } else { currentTranslate = directionProperty.get().doubleValue() * (startTranslate + directionProperty.get().doubleValue() * (eventPoint - startMouse)); } if (directionProperty.get().doubleValue() * currentTranslate <= 0) { // the drawer is hidden if (resizable) { maxSizeProperty.get().unbind(); prefSizeProperty.get().unbind(); if ((startSize - getDefaultDrawerSize()) + directionProperty.get().doubleValue() * currentTranslate > 0) { // change the side drawer size if dragging from hidden maxSizeProperty.get() .set(startSize + directionProperty.get().doubleValue() * currentTranslate); prefSizeProperty.get() .set(startSize + directionProperty.get().doubleValue() * currentTranslate); } else { // if the side drawer is not fully shown perform translation to show it , and set its default size maxSizeProperty.get().set(defaultSizeProperty.get()); maxSizeProperty.get().set(defaultSizeProperty.get()); translateProperty.set(directionProperty.get().doubleValue() * ((startSize - getDefaultDrawerSize()) + directionProperty.get().doubleValue() * currentTranslate)); } } else { translateProperty.set(currentTranslate); } } else { // the drawer is already shown if (resizable) { if (startSize + directionProperty.get() .doubleValue() * currentTranslate <= parentSizeProperty.get().get()) { // change the side drawer size after being shown maxSizeProperty.get().unbind(); prefSizeProperty.get().unbind(); maxSizeProperty.get() .set(startSize + directionProperty.get().doubleValue() * currentTranslate); prefSizeProperty.get() .set(startSize + directionProperty.get().doubleValue() * currentTranslate); } else { // bind the drawer size to its parent maxSizeProperty.get().bind(parentSizeProperty.get()); prefSizeProperty.get().bind(parentSizeProperty.get()); } } translateProperty.set(0); } } } }; private EventHandler mousePressedHandler = (mouseEvent) -> { translateTimer.setOnFinished(null); translateTimer.stop(); if (directionProperty.get() == DrawerDirection.RIGHT || directionProperty.get() == DrawerDirection.LEFT) { startMouse = mouseEvent.getSceneX(); } else { startMouse = mouseEvent.getSceneY(); } startTranslate = translateProperty.get(); startSize = sizeProperty.get().get(); }; private EventHandler mouseReleasedHandler = (mouseEvent) -> { if (directionProperty.get().doubleValue() * translateProperty.get() > directionProperty.get().doubleValue() * initTranslate.get() / 2) { // show side pane if (translateProperty.get() != 0.0) { partialOpen(); } } else { // hide the sidePane if (translateProperty.get() != initTranslate.get()) { partialClose(); } } if (sizeProperty.get().get() > getDefaultDrawerSize()) { tempDrawerSize = prefSizeProperty.get().get(); } else { tempDrawerSize = getDefaultDrawerSize(); } // reset drawer animation properties startMouse = -1; startTranslate = -1; startSize = sizeProperty.get().get(); }; private void partialClose() { translateTo = initTranslate.get(); translateTimer.setOnFinished(() -> { overlayPane.setMouseTransparent(true); fireEvent(new JFXDrawerEvent(JFXDrawerEvent.CLOSED)); }); translateTimer.start(); } private void partialOpen() { translateTo = 0; overlayPane.setMouseTransparent(!isOverLayVisible()); translateTimer.setOnFinished(() -> fireEvent(new JFXDrawerEvent(JFXDrawerEvent.OPENED))); translateTimer.start(); } /*************************************************************************** * * * Stylesheet Handling * * * **************************************************************************/ /** * Initialize the style class to 'jfx-drawer'. *

* This is the selector class from which CSS can be used to style * this control. */ private static final String DEFAULT_STYLE_CLASS = "jfx-drawer"; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy