/* * Copyright (c) 2013 by Gerrit Grunwald * * Licensed 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 eu.hansolo.enzo.radialmenu; import javafx.animation.Interpolator; import javafx.animation.RotateTransition; import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanPropertyBase; import javafx.css.PseudoClass; import javafx.scene.layout.Region; import javafx.util.Duration; /** * Created with IntelliJ IDEA. * User: hansolo * Date: 28.09.13 * Time: 02:54 * To change this template use File | Settings | File Templates. */ public class MenuButton extends Region { private static final double PREFERRED_SIZE = 45; private static final double MINIMUM_SIZE = 20; private static final double MAXIMUM_SIZE = 1024; private static final PseudoClass OPEN_PSEUDO_CLASS = PseudoClass.getPseudoClass("selected"); private RadialMenu radialMenu; private BooleanProperty open; private Region cross; private RotateTransition crossRotate; // ******************** Constructors ************************************** public MenuButton(final RadialMenu RADIAL_MENU) { radialMenu = RADIAL_MENU; getStyleClass().setAll("menu-button"); init(); initGraphics(); registerListeners(); } // ******************** Initialization ************************************ private void init() { if (Double.compare(getWidth(), 0) <= 0 || Double.compare(getHeight(), 0) <= 0 || Double.compare(getPrefWidth(), 0) <= 0 || Double.compare(getPrefHeight(), 0) <= 0) { setPrefSize(PREFERRED_SIZE, PREFERRED_SIZE); } if (Double.compare(getMinWidth(), 0) <= 0 || Double.compare(getMinHeight(), 0) <= 0) { setMinSize(MINIMUM_SIZE, MINIMUM_SIZE); } if (Double.compare(getMaxWidth(), 0) <= 0 || Double.compare(getMaxHeight(), 0) <= 0) { setMaxSize(MAXIMUM_SIZE, MAXIMUM_SIZE); } } private void initGraphics() { setPickOnBounds(false); cross = new Region(); cross.getStyleClass().add("cross"); cross.setMouseTransparent(true); crossRotate = new RotateTransition(Duration.millis(200), cross); crossRotate.setInterpolator(Interpolator.EASE_BOTH); // Add all nodes getChildren().addAll(cross); } private void registerListeners() { widthProperty().addListener(observable -> resize()); heightProperty().addListener(observable -> resize()); setOnMouseClicked(actionEvent -> setOpen(!isOpen())); } // ******************** Methods ******************************************* @Override protected double computePrefWidth(final double PREF_HEIGHT) { double prefHeight = PREFERRED_SIZE; if (PREF_HEIGHT != -1) { prefHeight = Math.max(0, PREF_HEIGHT - getInsets().getTop() - getInsets().getBottom()); } return super.computePrefWidth(prefHeight); } @Override protected double computePrefHeight(final double PREF_WIDTH) { double prefWidth = PREFERRED_SIZE; if (PREF_WIDTH != -1) { prefWidth = Math.max(0, PREF_WIDTH - getInsets().getLeft() - getInsets().getRight()); } return super.computePrefWidth(prefWidth); } @Override protected double computeMinWidth(final double MIN_HEIGHT) { return super.computeMinWidth(Math.max(MINIMUM_SIZE, MIN_HEIGHT - getInsets().getTop() - getInsets().getBottom())); } @Override protected double computeMinHeight(final double MIN_WIDTH) { return super.computeMinHeight(Math.max(MINIMUM_SIZE, MIN_WIDTH - getInsets().getLeft() - getInsets().getRight())); } @Override protected double computeMaxWidth(final double MAX_HEIGHT) { return super.computeMaxWidth(Math.min(MAXIMUM_SIZE, MAX_HEIGHT - getInsets().getTop() - getInsets().getBottom())); } @Override protected double computeMaxHeight(final double MAX_WIDTH) { return super.computeMaxHeight(Math.min(MAXIMUM_SIZE, MAX_WIDTH - getInsets().getLeft() - getInsets().getRight())); } public final boolean isOpen() { return null == open ? false : open.get(); } public final void setOpen(final boolean OPEN) { openProperty().set(OPEN); rotate(); } public final BooleanProperty openProperty() { if (null == open) { open = new BooleanPropertyBase(false) { @Override protected void invalidated() { pseudoClassStateChanged(OPEN_PSEUDO_CLASS, get()); } @Override public Object getBean() { return this; } @Override public String getName() { return "open"; } }; } return open; } private void rotate() { if (isOpen()) { crossRotate.setFromAngle(0); crossRotate.setToAngle(radialMenu.getOptions().isSimpleMode() ? -45 : -135); } else { crossRotate.setFromAngle(radialMenu.getOptions().isSimpleMode() ? -45 : -135); crossRotate.setToAngle(0); } crossRotate.play(); } private void resize() { cross.setPrefSize(0.44444 * getPrefWidth(), 0.44444 * getPrefHeight()); cross.relocate((getPrefWidth() - cross.getPrefWidth()) * 0.5, (getPrefHeight() - cross.getPrefHeight()) * 0.5); } }