Java color gradient generator
--------------- Gradient.java ------------------
import java.util.*;
import javafx.application.*;
import javafx.stage.*;
import javafx.scene.*;
import javafx.scene.layout.*;
import javafx.scene.paint.*;
import javafx.scene.canvas.*;
import javafx.scene.shape.*;
import javafx.scene.control.*;
import javafx.scene.input.*;
import javafx.geometry.*;
import javafx.scene.image.*;
public class Gradient extends Application {
double lastX;
List<Stop> stopsList = new ArrayList<>();
List<Pane> slidersList = new ArrayList<>();
double barWidth = 200, sliderWidth = 20, patternSize = 10;
Pane bar;
LinearGradient linearGradient;
ImagePattern patternTransparent;
Button addButton, delButton;
ColorPicker colorPicker;
int select;
@Override
public void start(Stage stage) {
stopsList.add(new Stop(0.2, Color.BLUE));
stopsList.add(new Stop(0.4, Color.RED));
stopsList.add(new Stop(0.6, Color.BLACK));
stopsList.add(new Stop(0.8, Color.TRANSPARENT));
stage.setScene(new Scene(gradientEdPane(), 350, 250));
stage.setOnCloseRequest(event -> { System.out.println(stopsList.toString()); });
stage.show();
}
Pane gradientEdPane() {
Pane gradientPane = new Pane();
gradientPane.setPrefSize(barWidth + sliderWidth, sliderWidth * 3.25 + 2);
gradientPane.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
gradientPane.setMaxSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE);
patternTransparent = patternTransparent();
bar = new Pane(new Rectangle(barWidth, sliderWidth * 2, patternTransparent),
new Rectangle(barWidth, sliderWidth * 2));
bar.relocate(sliderWidth / 2, 0);
((Rectangle)bar.getChildren().get(1)).setStrokeType(StrokeType.OUTSIDE);
((Rectangle)bar.getChildren().get(1)).setStrokeWidth(1);
((Rectangle)bar.getChildren().get(1)).setStroke(Color.BLACK);
colorPicker = new ColorPicker();
colorPicker.setOnAction((ae) -> {
stopsList.set(select, new Stop(stopsList.get(select).getOffset(), colorPicker.getValue()));
((Polygon)slidersList.get(select).getChildren().get(1)).setFill(colorPicker.getValue());
repaintGradient();
});
gradientPane.getChildren().add(bar);
stopsList.forEach((stop) -> { gradientPane.getChildren().add(createSlider(stop)); });
addButton = new Button("+");
addButton.setPrefWidth(30);
addButton.setOnAction((event) -> {
for (int i = 0; i < stopsList.size(); i++) {
double offset = stopsList.get(i).getOffset() * (1 - (sliderWidth + 4) / barWidth);
slidersList.get(i).setLayoutX(barWidth * offset);
stopsList.set(i, new Stop(offset , stopsList.get(i).getColor()));
}
Stop stop = new Stop(1, select >= 0 ? stopsList.get(select).getColor() : Color.TRANSPARENT);
stopsList.add(stop);
gradientPane.getChildren().add(createSlider(stop));
setDisableButtons();
selectSlider(slidersList.size() - 1);
repaintGradient();
});
delButton = new Button("-");
delButton.setPrefWidth(30);
delButton.setOnAction((event) -> {
assert select >= 0;
double offset = stopsList.get(select).getOffset();
gradientPane.getChildren().remove(slidersList.get(select));
stopsList.remove(select);
slidersList.remove(select);
setDisableButtons();
select = -1;
int il = -1, ir = -1;
for (int i = 0; i < stopsList.size(); i++) {
double off = stopsList.get(i).getOffset();
if (off < offset) { if(il < 0 || off > stopsList.get(il).getOffset()) il = i; }
else { if(ir < 0 || off < stopsList.get(ir).getOffset()) ir = i; }
}
if (il >= 0) selectSlider(il);
else if (ir >= 0) selectSlider(ir);
repaintGradient();
});
setDisableButtons();
select = -1;
if (stopsList.size() > 0) {
int m = -1;
for (int i = 0; i < stopsList.size(); i++)
if(m < 0 || stopsList.get(i).getOffset() < stopsList.get(m).getOffset()) m = i;
selectSlider(m);
}
repaintGradient();
HBox buttonPane = new HBox(6);
buttonPane.setPadding(new Insets(16, sliderWidth / 2, 0, sliderWidth / 2));
buttonPane.getChildren().addAll(colorPicker, addButton, delButton);
GridPane gradientEdPane = new GridPane();
gradientEdPane.add(gradientPane, 0, 0);
gradientEdPane.add(buttonPane, 0, 1);
gradientEdPane.setAlignment(Pos.CENTER);
return gradientEdPane;
}
double[] points = {
sliderWidth / 2.0, 0.0,
sliderWidth, sliderWidth / 2.0,
sliderWidth, sliderWidth * 1.25,
0.0, sliderWidth * 1.25,
0.0, sliderWidth / 2.0,
};
Pane createSlider(Stop stop) {
Pane slider = new Pane(new Polygon(points), new Polygon(points));
slidersList.add(slider);
slider.setLayoutX(barWidth * stop.getOffset());
slider.setLayoutY(sliderWidth * 2 + 2);
((Polygon)slider.getChildren().get(0)).setFill(patternTransparent);
((Polygon)slider.getChildren().get(1)).setFill(stop.getColor());
((Polygon)slider.getChildren().get(1)).setStrokeType(StrokeType.OUTSIDE);
((Polygon)slider.getChildren().get(1)).setStrokeWidth(1);
((Polygon)slider.getChildren().get(1)).setStroke(Color.BLACK);
slider.setOnMousePressed(me -> {
lastX = me.getX();
selectSlider(slidersList.indexOf(me.getSource()));
});
slider.setOnMouseDragged(me -> {
double layoutX = slider.getLayoutX() + me.getX() - lastX;
double offset = layoutX / barWidth;
offset = offset < 0 ? 0 : offset > 1 ? 1 : offset;
int ind = slidersList.indexOf(me.getSource());
if (Double.compare(offset, stopsList.get(ind).getOffset()) != 0) {
slider.setLayoutX(barWidth * offset);
stopsList.set(ind, new Stop(offset, stopsList.get(ind).getColor()));
repaintGradient();
}
});
return slider;
}
void setDisableButtons() {
if (stopsList.size() == 0) {
if(!delButton.isDisable()) {
delButton.setDisable(true);
colorPicker.setValue(Color.TRANSPARENT);
colorPicker.setDisable(true);
}
} else if (delButton.isDisable()) {
delButton.setDisable(false);
colorPicker.setDisable(false);
}
}
void repaintGradient() {
linearGradient = new LinearGradient(0, 0, 1, 0, true, CycleMethod.NO_CYCLE, stopsList);
((Rectangle)bar.getChildren().get(1)).setFill(linearGradient);
}
void selectSlider(int newSelect) {
if (newSelect != select) {
if (select >= 0) {
((Polygon)slidersList.get(select).getChildren().get(1)).setStrokeWidth(1);
((Polygon)slidersList.get(select).getChildren().get(1)).setStroke(Color.BLACK);
}
assert newSelect >= 0;
((Polygon)slidersList.get(newSelect).getChildren().get(1)).setStrokeWidth(2);
((Polygon)slidersList.get(newSelect).getChildren().get(1)).setStroke(Color.DODGERBLUE);
colorPicker.setValue(stopsList.get(newSelect).getColor());
slidersList.get(newSelect).toFront();
select = newSelect;
}
}
ImagePattern patternTransparent() {
Canvas canvas = new Canvas(patternSize, patternSize);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill(Color.WHITE);
gc.fillRect(0, 0, patternSize, patternSize);
gc.setFill(Color.rgb(205, 205, 205));
gc.fillRect(0, 0, patternSize / 2, patternSize / 2);
gc.fillRect(patternSize / 2, patternSize / 2, patternSize, patternSize);
WritableImage image = canvas.snapshot(new SnapshotParameters(), null);
return new ImagePattern(image, 0, 0, patternSize, patternSize, false);
}
}