/*******************************************************************************
* Copyright (c) 2014, 2015 itemis AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Alexander Nyßen (itemis AG) - initial API and implementation
*
*******************************************************************************/
package org.eclipse.gef.fx.swt.controls;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.embed.swt.FXCanvas;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.LinearGradient;
import javafx.scene.paint.Paint;
import javafx.scene.paint.Stop;
/**
* The {@link FXSimpleLinearGradientPicker} allows the selection of two colors
* from which a gradient is constructed.
*
* @author anyssen
*
*/
public class FXSimpleLinearGradientPicker extends Composite {
/**
* Property name used in change events related to
* {@link #simpleLinearGradientProperty()}.
*/
public static final String SIMPLE_LINEAR_GRADIENT_PROPERTY = "simpleLinearGradient";
/**
* Creates a simple color gradient from the given start color to the given
* end color.
*
* @param c1
* The start {@link Color}.
* @param c2
* The end {@link Color}.
* @return The resulting {@link LinearGradient}.
*/
public static LinearGradient createSimpleLinearGradient(Color c1,
Color c2) {
// TODO: add angle
Stop[] stops = new Stop[] { new Stop(0, c1), new Stop(1, c2) };
return new LinearGradient(0, 0, 1, 0, true, CycleMethod.NO_CYCLE,
stops);
}
/**
* Returns <code>true</code> if the given {@link Paint} is a "simple"
* gradient, i.e. it has exactly 2 stops. Otherwise returns
* <code>false</code>.
*
* @param paint
* The {@link Paint} in question.
* @return <code>true</code> if the given {@link Paint} is a simple
* gradient, otherwise <code>false</code>.
*/
public static boolean isSimpleLinearGradient(Paint paint) {
if (paint instanceof LinearGradient) {
return ((LinearGradient) paint).getStops().size() == 2;
}
return false;
}
private ObjectProperty<LinearGradient> simpleLinearGradient = new SimpleObjectProperty<>(
this, SIMPLE_LINEAR_GRADIENT_PROPERTY);
private FXColorPicker color1Picker;
private FXColorPicker color2Picker;
/**
* Constructs a new {@link FXSimpleLinearGradientPicker}.
*
* @param parent
* The parent {@link Composite}.
* @param color1
* The first color of the initial simple {@link LinearGradient}.
* @param color2
* The second color of the initial simple {@link LinearGradient}.
*/
public FXSimpleLinearGradientPicker(Composite parent, Color color1,
Color color2) {
super(parent, SWT.NONE);
setLayout(new FillLayout());
final FXCanvas canvas = new FXCanvas(this, SWT.NONE);
HBox root = new HBox();
root.setStyle("-fx-background-color: transparent;");
VBox colorEditorsBox = new VBox();
colorEditorsBox.setSpacing(5);
root.getChildren().add(colorEditorsBox);
color1Picker = new FXColorPicker(canvas, color1);
colorEditorsBox.getChildren()
.add(new FXControlAdapter<Control>(color1Picker));
color1Picker.colorProperty().addListener(new ChangeListener<Color>() {
@Override
public void changed(ObservableValue<? extends Color> observable,
Color oldValue, Color newValue) {
setSimpleLinearGradient(createSimpleLinearGradient(newValue,
color2Picker.getColor()));
}
});
color2Picker = new FXColorPicker(canvas, color2);
colorEditorsBox.getChildren()
.add(new FXControlAdapter<Control>(color2Picker));
color2Picker.colorProperty().addListener(new ChangeListener<Color>() {
@Override
public void changed(ObservableValue<? extends Color> observable,
Color oldValue, Color newValue) {
setSimpleLinearGradient(createSimpleLinearGradient(
color1Picker.getColor(), newValue));
}
});
Scene scene = new Scene(root);
// copy background color from parent composite
org.eclipse.swt.graphics.Color backgroundColor = parent.getBackground();
scene.setFill(Color.rgb(backgroundColor.getRed(),
backgroundColor.getGreen(), backgroundColor.getBlue()));
canvas.setScene(scene);
// initialize simple gradient
setSimpleLinearGradient(createSimpleLinearGradient(color1, color2));
}
/**
* Returns the currently selected simple gradient.
*
* @return The currently selected simple gradient.
*/
public LinearGradient getSimpleLinearGradient() {
return simpleLinearGradient.get();
}
/**
* Changes the currently selected gradient to the given value.
*
* @param simpleLinearGradient
* The new simple {@link LinearGradient} to select.
*/
public void setSimpleLinearGradient(LinearGradient simpleLinearGradient) {
if (!isSimpleLinearGradient(simpleLinearGradient)) {
throw new IllegalArgumentException("Given value '"
+ simpleLinearGradient + "' is no simple linear gradient");
}
this.simpleLinearGradient.set(simpleLinearGradient);
// a simple linear gradient contains two stops
List<Stop> stops = simpleLinearGradient.getStops();
if (!color1Picker.getColor().equals(stops.get(0).getColor())) {
color1Picker.setColor(stops.get(0).getColor());
}
if (!color2Picker.getColor().equals(stops.get(1).getColor())) {
color2Picker.setColor(stops.get(1).getColor());
}
}
/**
* Returns a writable property for the simple linear gradient.
*
* @return A writable property.
*/
public Property<LinearGradient> simpleLinearGradientProperty() {
return simpleLinearGradient;
}
}