blob: c0e21893dbbf9706a07fd6fe8a1713e7a7ac97a4 [file] [log] [blame]
package org.eclipse.fx.ui.controls.form;
import org.eclipse.fx.core.Status;
import org.eclipse.fx.core.Status.State;
import org.osgi.service.component.annotations.Component;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.css.PseudoClass;
import javafx.scene.Node;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.control.SkinBase;
import javafx.scene.control.Tooltip;
@Component
public class GraphicDecorator implements NodeDecorator {
static final String BASE_STYLESHEET = GraphicDecorator.class.getResource("graphic-status-decorator.css").toExternalForm(); //$NON-NLS-1$
public enum Location {
TOP_LEFT,
TOP_RIGHT,
BOTTOM_LEFT,
BOTTOM_RIGHT
}
// public interface LocationProvider extends Predicate<Control> {
// public Location getLocation(Control node);
// }
private Location location;
public GraphicDecorator() {
this(Location.TOP_LEFT);
}
public GraphicDecorator(Location location) {
this.location = location;
}
@Override
public DecoratedNode decorate(Node node) {
if( node instanceof Control ) {
return new GraphicDecoratedControl((Control) node, this.location);
}
throw new IllegalArgumentException("Unable to decorate '"+node+"'"); //$NON-NLS-1$//$NON-NLS-2$
}
static class GraphicDecoratedControl implements DecoratedNode {
private final Label icon;
private final ObjectProperty<Status> statusProperty = new SimpleObjectProperty<Status>(this, "status", Status.ok()); //$NON-NLS-1$
private static PseudoClass error = PseudoClass.getPseudoClass("error");
private static PseudoClass warning = PseudoClass.getPseudoClass("warning");
private static PseudoClass ok = PseudoClass.getPseudoClass("ok");
private static PseudoClass cancel = PseudoClass.getPseudoClass("cancel");
public GraphicDecoratedControl(Control c, Location location) {
this.icon = new Label() {
@Override
public String getUserAgentStylesheet() {
return BASE_STYLESHEET;
}
};
this.icon.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
this.icon.getStyleClass().add("status-decorator-icon"); //$NON-NLS-1$
this.icon.setManaged(false);
if( c.getSkin() != null ) {
((SkinBase<?>)c.getSkin()).getChildren().add(this.icon);
}
c.skinProperty().addListener( ( ob, ol, ne ) -> {
if( ol != null ) {
((SkinBase<?>)ol).getChildren().remove(this.icon);
}
if( ne != null ) {
((SkinBase<?>)ne).getChildren().add(this.icon);
}
});
if( location == Location.TOP_LEFT ) {
this.icon.translateXProperty().bind(this.icon.widthProperty().divide(-2));
this.icon.translateYProperty().bind(this.icon.heightProperty().divide(-2));
} else if( location == Location.TOP_RIGHT ) {
this.icon.translateXProperty().bind(Bindings.createDoubleBinding(() -> {
return Double.valueOf(c.getWidth() - this.icon.widthProperty().get() / 2);
},this.icon.widthProperty(), c.widthProperty()));
this.icon.translateYProperty().bind(this.icon.heightProperty().divide(-2));
} else if( location == Location.BOTTOM_LEFT ) {
this.icon.translateXProperty().bind(this.icon.widthProperty().divide(-2));
this.icon.translateYProperty().bind(Bindings.createDoubleBinding(() -> {
return Double.valueOf(c.getHeight() - this.icon.heightProperty().get() / 2);
}, this.icon.heightProperty(), c.heightProperty()));
} else if( location == Location.BOTTOM_RIGHT ) {
this.icon.translateXProperty().bind(Bindings.createDoubleBinding(() -> {
return Double.valueOf(c.getWidth() - this.icon.widthProperty().get() / 2);
},this.icon.widthProperty(), c.widthProperty()));
this.icon.translateYProperty().bind(Bindings.createDoubleBinding(() -> {
return Double.valueOf(c.getHeight() - this.icon.heightProperty().get() / 2);
}, this.icon.heightProperty(), c.heightProperty()));
}
updatePseudoState(this.icon, this.statusProperty.getValue());
this.statusProperty.addListener( (o, ol, ne) -> {
updatePseudoState(this.icon, ne);
});
this.icon.translateXProperty().addListener( o -> {
System.err.println(this.icon.translateXProperty().get());
});
}
private static void updatePseudoState(Label statusIcon, Status status) {
statusIcon.pseudoClassStateChanged(error, status.getState() == State.ERROR);
statusIcon.pseudoClassStateChanged(warning, status.getState() == State.WARNING);
statusIcon.pseudoClassStateChanged(ok, status.getState() == State.OK);
statusIcon.pseudoClassStateChanged(cancel, status.getState() == State.CANCEL);
statusIcon.autosize();
if( statusIcon.getTooltip() == null ) {
if( status.getState() != State.OK ) {
statusIcon.setTooltip(new Tooltip(status.getMessage()));
}
} else {
statusIcon.getTooltip().setText(status.getMessage());
}
}
@Override
public ObjectProperty<Status> statusProperty() {
return this.statusProperty;
}
@Override
public void setStatus(Status status) {
statusProperty().set(status);
}
@Override
public Status getStatus() {
return statusProperty().get();
}
}
}