jfxtras.labs.scene.control.radialmenu.RadialContainerMenuItem Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jfxtras-labs Show documentation
Show all versions of jfxtras-labs Show documentation
Experimental components for JavaFX 2
/**
* RadialContainerMenuItem.java
*
* Copyright (c) 2011-2014, JFXtras
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the organization nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jfxtras.labs.scene.control.radialmenu;
import java.util.ArrayList;
import java.util.List;
import javafx.animation.Animation.Status;
import javafx.animation.FadeTransition;
import javafx.animation.FadeTransitionBuilder;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polyline;
import javafx.scene.shape.PolylineBuilder;
import javafx.util.Duration;
public class RadialContainerMenuItem extends RadialMenuItem {
private boolean selected = false;
private final Group childAnimGroup = new Group();
private FadeTransition fadeIn = null;
private FadeTransition fadeOut = null;
protected List items = new ArrayList();
protected Polyline arrow = PolylineBuilder.create()
.points(-5.0, -5.0, 5.0, 0.0, -5.0, 5.0, -5.0, -5.0)
.fill(Color.GRAY).stroke(null).build();
public RadialContainerMenuItem(final double menuSize, final Node graphic) {
super(menuSize, graphic);
this.initialize();
}
public RadialContainerMenuItem(final double menuSize, final String text,
final Node graphic) {
super(menuSize, text, graphic);
this.initialize();
}
private void initialize() {
this.childAnimGroup.setVisible(false);
this.visibleProperty().addListener(new ChangeListener() {
@Override
public void changed(final ObservableValue extends Boolean> arg0,
final Boolean arg1, final Boolean arg2) {
if (!arg0.getValue()) {
RadialContainerMenuItem.this.childAnimGroup
.setVisible(false);
RadialContainerMenuItem.this.setSelected(false);
}
}
});
this.getChildren().add(this.childAnimGroup);
this.fadeIn = FadeTransitionBuilder.create().node(this.childAnimGroup)
.duration(Duration.millis(400)).fromValue(0.0).toValue(1.0)
.build();
this.fadeOut = FadeTransitionBuilder.create().node(this.childAnimGroup)
.duration(Duration.millis(400)).fromValue(1.0).toValue(0.0)
.onFinished(new EventHandler() {
@Override
public void handle(final ActionEvent arg0) {
RadialContainerMenuItem.this.childAnimGroup
.setVisible(false);
}
}).build();
this.getChildren().add(this.arrow);
}
public void addMenuItem(final RadialMenuItem item) {
item.backgroundColorProperty().bind(this.backgroundColor);
item.backgroundMouseOnColorProperty().bind(this.backgroundMouseOnColor);
item.innerRadiusProperty().bind(this.radius);
item.radiusProperty().bind(
this.radius.multiply(2).subtract(this.innerRadius));
item.offsetProperty().bind(this.offset.multiply(2.0));
item.strokeColorProperty().bind(this.strokeColor);
item.clockwiseProperty().bind(this.clockwise);
item.backgroundVisibleProperty().bind(this.backgroundVisible);
item.strokeVisibleProperty().bind(this.strokeVisible);
this.items.add(item);
this.childAnimGroup.getChildren().add(item);
double offset = 0;
for (final RadialMenuItem it : this.items) {
it.startAngleProperty().bind(this.startAngleProperty().add(offset));
offset += it.getMenuSize();
}
}
public void removeMenuItem(final RadialMenuItem item) {
this.items.remove(item);
this.childAnimGroup.getChildren().remove(item);
item.backgroundColorProperty().unbind();
item.backgroundMouseOnColorProperty().unbind();
item.innerRadiusProperty().unbind();
item.radiusProperty().unbind();
item.offsetProperty().unbind();
item.strokeColorProperty().unbind();
item.clockwiseProperty().unbind();
item.backgroundVisibleProperty().unbind();
item.strokeVisibleProperty().unbind();
}
public void removeMenuItem(final int itemIndex) {
final RadialMenuItem item = this.items.get(itemIndex);
this.removeMenuItem(item);
}
@Override
protected void redraw() {
super.redraw();
if (this.selected) {
this.path
.setFill(this.backgroundVisible.get() ? (this.selected
&& this.backgroundMouseOnColor.get() != null ? this.backgroundMouseOnColor
.get() : this.backgroundColor.get())
: null);
}
if (this.arrow != null) {
this.arrow.setFill(this.backgroundVisible.get() ? (this.mouseOn
&& this.strokeColor.get() != null ? this.strokeColor.get()
: this.strokeColor.get()) : null);
this.arrow.setStroke(this.strokeVisible.get() ? this.strokeColor
.get() : null);
if (!this.clockwise.get()) {
this.arrow
.setRotate(-(this.startAngle.get() + this.menuSize / 2.0));
this.arrow.setTranslateX((this.radius.get() - this.arrow
.getBoundsInLocal().getWidth() / 2.0)
* Math.cos(Math.toRadians(this.startAngle.get()
+ this.menuSize / 2.0)) + this.translateX);
this.arrow.setTranslateY(-(this.radius.get() - this.arrow
.getBoundsInLocal().getHeight() / 2.0)
* Math.sin(Math.toRadians(this.startAngle.get()
+ this.menuSize / 2.0)) + this.translateY);
} else {
this.arrow.setRotate(this.startAngle.get() + this.menuSize
/ 2.0);
this.arrow.setTranslateX((this.radius.get() - this.arrow
.getBoundsInLocal().getWidth() / 2.0)
* Math.cos(Math.toRadians(this.startAngle.get()
+ this.menuSize / 2.0)) + this.translateX);
this.arrow.setTranslateY((this.radius.get() - this.arrow
.getBoundsInLocal().getHeight() / 2.0)
* Math.sin(Math.toRadians(this.startAngle.get()
+ this.menuSize / 2.0)) + this.translateY);
}
}
}
@Override
void setSelected(final boolean selected) {
this.selected = selected;
if (this.selected) {
double startOpacity = 0;
if (this.fadeOut.getStatus() == Status.RUNNING) {
this.fadeOut.stop();
startOpacity = this.childAnimGroup.getOpacity();
}
// draw Children
this.childAnimGroup.setOpacity(startOpacity);
this.childAnimGroup.setVisible(true);
this.fadeIn.fromValueProperty().set(startOpacity);
this.fadeIn.playFromStart();
} else {
// draw Children
double startOpacity = 1.0;
if (this.fadeIn.getStatus() == Status.RUNNING) {
this.fadeIn.stop();
startOpacity = this.childAnimGroup.getOpacity();
}
this.fadeOut.fromValueProperty().set(startOpacity);
this.fadeOut.playFromStart();
}
this.redraw();
}
@Override
boolean isSelected() {
return this.selected;
}
}