Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.sun.javafx.scene.control.skin.ColorPalette Maven / Gradle / Ivy
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.javafx.scene.control.skin;
import javafx.css.PseudoClass;
import javafx.scene.control.ColorPicker;
import java.util.List;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.NodeOrientation;
import javafx.geometry.Pos;
import javafx.geometry.Side;
import javafx.scene.control.*;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.StrokeType;
public class ColorPalette extends VBox {
private static final int SQUARE_SIZE = 15;
private static final int NUM_OF_COLUMNS = 12;
private static final int NUM_OF_ROWS = 10;
private static final int LABEL_GAP = 2;
private boolean customColorAdded = false;
ColorPickerGrid colorPickerGrid;
ColorPicker colorPicker;
GridPane customColorGrid = new GridPane();
Hyperlink customColorLink = new Hyperlink("Custom Color..");
Separator separator = new Separator();
Label customColorLabel = new Label("Custom Colors");
CustomColorDialog customColorDialog = null;
private final List customSquares = FXCollections.observableArrayList();
private PopupControl popupControl;
private ColorSquare focusedSquare;
private ContextMenu contextMenu = null;
private Color mouseDragColor = null;
private boolean dragDetected = false;
public ColorPalette(Color initPaint, final ColorPicker colorPicker) {
getStyleClass().add("color-palette");
this.colorPicker = colorPicker;
colorPickerGrid = new ColorPickerGrid(initPaint);
colorPickerGrid.requestFocus();
colorPickerGrid.setFocusTraversable(true);
customColorLabel.setAlignment(Pos.CENTER_LEFT);
customColorLink.setPrefWidth(colorPickerGrid.prefWidth(-1));
customColorLink.setAlignment(Pos.CENTER);
customColorLink.setFocusTraversable(true);
customColorLink.setVisited(true); // so that it always appears blue
customColorLink.setOnAction(new EventHandler() {
@Override public void handle(ActionEvent t) {
if (customColorDialog == null) {
customColorDialog = new CustomColorDialog(popupControl);
customColorDialog.customColorProperty().addListener(new ChangeListener() {
@Override public void changed(ObservableValue ov,
Color t, Color t1) {
colorPicker.setValue(customColorDialog.customColorProperty().get());
}
});
customColorDialog.setOnSave(new Runnable() {
@Override
public void run() {
Color customColor = customColorDialog.customColorProperty().get();
ColorSquare cs = new ColorSquare(customColor, true);
customSquares.add(cs);
buildCustomColors();
colorPicker.getCustomColors().add(customColor);
updateSelection(customColor);
Event.fireEvent(colorPicker, new ActionEvent());
colorPicker.hide();
}
});
customColorDialog.setOnUse(new Runnable() {
@Override
public void run() {
Event.fireEvent(colorPicker, new ActionEvent());
colorPicker.hide();
}
});
}
customColorDialog.setCurrentColor(colorPicker.valueProperty().get());
if (popupControl != null) popupControl.setAutoHide(false);
customColorDialog.show();
if (popupControl != null) popupControl.setAutoHide(true);
}
});
initNavigation();
customColorGrid.getStyleClass().add("color-picker-grid");
customColorGrid.setVisible(false);
customColorGrid.setFocusTraversable(true);
for (Color c : colorPicker.getCustomColors()) {
customSquares.add(new ColorSquare(c, true));
}
buildCustomColors();
colorPicker.getCustomColors().addListener(new ListChangeListener() {
@Override public void onChanged(Change change) {
customSquares.clear();
for (Color c : colorPicker.getCustomColors()) {
customSquares.add(new ColorSquare(c, true));
}
buildCustomColors();
}
});
getChildren().addAll(colorPickerGrid, customColorLabel, customColorGrid, separator, customColorLink);
}
private void buildCustomColors() {
int customColumnIndex = 0;
int customRowIndex = 0;
int remainingSquares = customSquares.size()%NUM_OF_COLUMNS;
int numEmpty = (remainingSquares == 0) ? 0 : NUM_OF_COLUMNS - remainingSquares;
customColorGrid.getChildren().clear();
if (customSquares.isEmpty()) {
customColorLabel.setVisible(false);
customColorLabel.setManaged(false);
customColorGrid.setVisible(false);
customColorGrid.setManaged(false);
return;
} else {
customColorLabel.setVisible(true);
customColorLabel.setManaged(true);
customColorGrid.setVisible(true);
customColorGrid.setManaged(true);
if (contextMenu == null) {
MenuItem item = new MenuItem("Remove Color");
item.setOnAction(new EventHandler() {
@Override public void handle(ActionEvent e) {
ColorSquare square = (ColorSquare)contextMenu.getOwnerNode();
colorPicker.getCustomColors().remove(square.rectangle.getFill());
customSquares.remove(square);
buildCustomColors();
}
});
contextMenu = new ContextMenu(item);
}
}
for(ColorSquare square : customSquares) {
customColorGrid.add(square, customColumnIndex, customRowIndex);
customColumnIndex++;
if (customColumnIndex == NUM_OF_COLUMNS) {
customColumnIndex = 0;
customRowIndex++;
}
}
for (int i = 0; i < numEmpty; i++) {
ColorSquare emptySquare = new ColorSquare(null);
customColorGrid.add(emptySquare, customColumnIndex, customRowIndex);
customColumnIndex++;
}
requestLayout();
}
private void initNavigation() {
setOnKeyPressed(new EventHandler() {
@Override public void handle(KeyEvent ke) {
switch (ke.getCode()) {
case LEFT:
if (getEffectiveNodeOrientation() == NodeOrientation.RIGHT_TO_LEFT) {
processRightKey(ke);
} else {
processLeftKey(ke);
}
break;
case RIGHT:
if (getEffectiveNodeOrientation() == NodeOrientation.RIGHT_TO_LEFT) {
processLeftKey(ke);
} else {
processRightKey(ke);
}
break;
case UP:
processUpKey(ke);
break;
case DOWN:
processDownKey(ke);
break;
case ENTER:
processSelectKey(ke);
break;
default: // no-op
}
}
});
}
private void processSelectKey(KeyEvent ke) {
if (focusedSquare != null) focusedSquare.selectColor(ke);
}
private void processLeftKey(KeyEvent ke) {
int index;
for (index = (NUM_OF_ROWS*NUM_OF_COLUMNS)-1; index >= 0; index--) {
ColorSquare cs = colorPickerGrid.getSquares().get(index);
if (cs == focusedSquare) {
ColorSquare prevSquare = colorPickerGrid.getSquares().get((index != 0) ?
(index-1) : (NUM_OF_ROWS*NUM_OF_COLUMNS)-1);
prevSquare.requestFocus();
focusedSquare = prevSquare;
return;
}
}
// check custom colors
int len = customColorGrid.getChildren().size();
for (index = len-1; index >= 0; index--) {
ColorSquare cs = (ColorSquare)customColorGrid.getChildren().get(index);
if (cs == focusedSquare) {
ColorSquare prevSquare = (ColorSquare)customColorGrid.getChildren().get((index != 0) ?
(index-1) : len-1);
prevSquare.requestFocus();
focusedSquare = prevSquare;
return;
}
}
if (index == -1) {
ColorSquare cs = colorPickerGrid.getSquares().get((NUM_OF_ROWS*NUM_OF_COLUMNS)-1);
focusedSquare = cs;
cs.requestFocus();;
}
}
private void processUpKey(KeyEvent ke) {
int index;
for (index = (NUM_OF_ROWS*NUM_OF_COLUMNS)-1; index >= 0; index--) {
ColorSquare cs = colorPickerGrid.getSquares().get(index);
if (cs == focusedSquare) {
ColorSquare prevSquare = colorPickerGrid.getSquares().get((index-12 >= 0)?
(index-12) : ((NUM_OF_ROWS-1)*NUM_OF_COLUMNS)+index);
prevSquare.requestFocus();
focusedSquare = prevSquare;
return;
}
}
int len = customColorGrid.getChildren().size();
for (index = len-1; index >= 0; index--) {
// check custom colors
ColorSquare cs = (ColorSquare)customColorGrid.getChildren().get(index);
ColorSquare prevSquare = null;
if (cs == focusedSquare) {
if (index -12 >= 0) {
prevSquare = (ColorSquare)customColorGrid.getChildren().get(index-12);
} else {
int rowIndex = GridPane.getRowIndex(customColorGrid.getChildren().get(len-1));
prevSquare = (ColorSquare)customColorGrid.getChildren().get((rowIndex*NUM_OF_COLUMNS)+index);
}
prevSquare.requestFocus();
focusedSquare = prevSquare;
return;
}
}
if (index == -1) {
ColorSquare cs = colorPickerGrid.getSquares().get((NUM_OF_ROWS*NUM_OF_COLUMNS)-1);
focusedSquare = cs;
focusedSquare.requestFocus();
}
}
private void processRightKey(KeyEvent ke) {
int index;
for (index = 0; index < (NUM_OF_ROWS*NUM_OF_COLUMNS); index++) {
ColorSquare cs = colorPickerGrid.getSquares().get(index);
if (cs == focusedSquare) {
ColorSquare prevSquare = colorPickerGrid.getSquares().get(
(index != (NUM_OF_ROWS*NUM_OF_COLUMNS)-1) ? (index+1) : 0);
prevSquare.requestFocus();
focusedSquare = prevSquare;
return;
}
}
// check custom colors
int len = customColorGrid.getChildren().size();
for (index = 0; index < len; index++) {
ColorSquare cs = (ColorSquare)customColorGrid.getChildren().get(index);
if (cs == focusedSquare) {
ColorSquare prevSquare = (ColorSquare)customColorGrid.getChildren().get(
(index != len-1) ? (index+1) : 0);
prevSquare.requestFocus();
focusedSquare = prevSquare;
return;
}
}
if (index == len) {
ColorSquare cs = colorPickerGrid.getSquares().get(0);
focusedSquare = cs;
focusedSquare.requestFocus();
}
}
private void processDownKey(KeyEvent ke) {
int index;
for (index = 0; index < (NUM_OF_ROWS*NUM_OF_COLUMNS); index++) {
ColorSquare cs = colorPickerGrid.getSquares().get(index);
if (cs == focusedSquare) {
ColorSquare prevSquare = colorPickerGrid.getSquares().get((index+12 < NUM_OF_ROWS*NUM_OF_COLUMNS)?
(index+12) : index-((NUM_OF_ROWS-1)*NUM_OF_COLUMNS));
prevSquare.requestFocus();
focusedSquare = prevSquare;
return;
}
}
// check custom colors
int len = customColorGrid.getChildren().size();
for (index = 0; index < len; index++) {
ColorSquare cs = (ColorSquare)customColorGrid.getChildren().get(index);
ColorSquare prevSquare = null;
if (cs == focusedSquare) {
if (index+12 < len) {
prevSquare = (ColorSquare)customColorGrid.getChildren().get(index+12);
} else {
int rowIndex = GridPane.getRowIndex(customColorGrid.getChildren().get(len-1));
prevSquare = (ColorSquare)customColorGrid.getChildren().get(index-(rowIndex)*NUM_OF_COLUMNS);
}
prevSquare.requestFocus();
focusedSquare = prevSquare;
return;
}
}
if (index == len) {
ColorSquare cs = colorPickerGrid.getSquares().get(0);
focusedSquare.requestFocus();
focusedSquare = cs;
}
}
public void setPopupControl(PopupControl pc) {
this.popupControl = pc;
}
public ColorPickerGrid getColorGrid() {
return colorPickerGrid;
}
//
// @Override protected void layoutChildren() {
// double x = getInsets().getLeft();
// double y = getInsets().getTop();
//// double popupWidth = cpg.prefWidth(-1) + paddingX+getInsets().getRight();
//// double popupHeight = cpg.prefHeight(-1) + getInsets().getTop() + getInsets().getBottom();
// colorPickerGrid.relocate(x, y);
// y = y+colorPickerGrid.prefHeight(-1)+GAP;
// if (customColorAdded) {
// if (customColorLabel.isVisible()) {
// customColorLabel.resizeRelocate(x, y, colorPickerGrid.prefWidth(-1), customColorLabel.prefHeight(y));
// y = y+customColorLabel.prefHeight(-1)+LABEL_GAP;
// }
// customColorGrid.relocate(x, y);
// y = y+customColorGrid.prefHeight(-1)+GAP;
// }
// separator.resizeRelocate(x, y, colorPickerGrid.prefWidth(-1), separator.prefHeight(-1));
// y = y+separator.prefHeight(-1)+GAP;
// customColorLink.resizeRelocate(x, y, colorPickerGrid.prefWidth(-1), customColorLink.prefHeight(-1));
// }
//
// @Override protected double computePrefWidth(double height) {
// return getInsets().getLeft() + colorPickerGrid.prefWidth(-1) + getInsets().getRight();
// }
//
// @Override protected double computePrefHeight(double width) {
// double totalHeight = colorPickerGrid.prefHeight(-1) + GAP +
// ((customColorAdded) ?
// (customColorGrid.prefHeight(-1)+customColorLabel.prefHeight(-1))+LABEL_GAP+GAP : 0) +
// separator.prefHeight(-1) + GAP + customColorLink.prefHeight(-1);
// return getInsets().getTop() + totalHeight + getInsets().getBottom();
// }
//
public boolean isCustomColorDialogShowing() {
if (customColorDialog != null) return customColorDialog.isVisible();
return false;
}
class ColorSquare extends StackPane {
Rectangle rectangle;
boolean isCustom = false;
boolean isEmpty = false;
public ColorSquare(Color color) {
this(color, false);
}
public ColorSquare(Color color, boolean value) {
// Add style class to handle selected color square
getStyleClass().add("color-square");
setFocusTraversable(true);
this.isCustom = value;
rectangle = new Rectangle(SQUARE_SIZE, SQUARE_SIZE);
setFocusTraversable(true);
if (color == null) {
rectangle.setFill(Color.WHITE );
isEmpty = true;
}
else {
rectangle.setFill(color);
}
// setFill(color);
rectangle.setSmooth(false);
// Utils.setBlocksMouse(this, true);
rectangle.setStrokeType(StrokeType.INSIDE);
String tooltipStr = ColorPickerSkin.colorValueToWeb(color);
Tooltip.install(this, new Tooltip((tooltipStr == null) ? "" : tooltipStr));
rectangle.getStyleClass().add("color-rect");
addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler() {
@Override public void handle(MouseEvent event) {
toFront();
}
});
addEventHandler(MouseEvent.MOUSE_RELEASED, new EventHandler() {
@Override public void handle(MouseEvent event) {
if (!dragDetected && event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 1) {
if (!isEmpty) {
Color fill = (Color)rectangle.getFill();
colorPicker.setValue(fill);
colorPicker.fireEvent(new ActionEvent());
updateSelection(fill);
event.consume();
}
colorPicker.hide();
} else if (event.getButton() == MouseButton.SECONDARY ||
event.getButton() == MouseButton.MIDDLE) {
if (isCustom && contextMenu != null) {
if (!contextMenu.isShowing()) {
contextMenu.show(ColorSquare.this, Side.RIGHT, 0, 0);
Utils.addMnemonics(contextMenu, ColorSquare.this.getScene(), colorPicker.impl_isShowMnemonics());
}
else {
contextMenu.hide();
Utils.removeMnemonics(contextMenu, ColorSquare.this.getScene());
}
}
}
}
});
focusedProperty().addListener(new ChangeListener() {
@Override
public void changed(ObservableValue ov, Boolean t, Boolean t1) {
}
});
addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler() {
@Override public void handle(MouseEvent event) {
focusedSquare = ColorSquare.this;
focusedSquare.requestFocus();
}
});
getChildren().add(rectangle);
}
public void selectColor(KeyEvent event) {
if (rectangle.getFill() != null) {
if (rectangle.getFill() instanceof Color) {
colorPicker.setValue((Color) rectangle.getFill());
colorPicker.fireEvent(new ActionEvent());
}
event.consume();
}
colorPicker.hide();
}
private ReadOnlyBooleanWrapper selected;
protected final void setSelected(boolean value) {
selectedPropertyImpl().set(value);
}
public final boolean isSelected() { return selected == null ? false : selected.get(); }
public ReadOnlyBooleanProperty selectedProperty() {
return selectedPropertyImpl().getReadOnlyProperty();
}
private ReadOnlyBooleanWrapper selectedPropertyImpl() {
if (selected == null) {
selected = new ReadOnlyBooleanWrapper() {
@Override protected void invalidated() {
pseudoClassStateChanged(SELECTED_PSEUDOCLASS_STATE, get());
}
@Override
public Object getBean() {
return ColorSquare.this;
}
@Override
public String getName() {
return "selected";
}
};
}
return selected;
}
private final PseudoClass SELECTED_PSEUDOCLASS_STATE =
PseudoClass.getPseudoClass("selected");
}
public void clearFocus() {
colorPickerGrid.requestFocus();
}
// The skin can update selection if colorpicker value changes..
public void updateSelection(Color color) {
for (ColorSquare c : colorPickerGrid.getSquares()) {
c.setSelected(c.rectangle.getFill().equals(color));
}
// check custom colors
for (ColorSquare cs : customSquares) {
cs.setSelected(cs.rectangle.getFill().equals(color));
}
}
class ColorPickerGrid extends GridPane {
private final List squares;
public ColorPickerGrid(Color initPaint) {
getStyleClass().add("color-picker-grid");
setId("ColorCustomizerColorGrid");
int columnIndex = 0, rowIndex = 0;
setFocusTraversable(true);
squares = FXCollections.observableArrayList();
int numColors = rawValues.length / 3;
Color[] colors = new Color[numColors];
for (int i = 0; i < numColors; i++) {
colors[i] = new Color(rawValues[(i * 3)] / 255,
rawValues[(i * 3) + 1] / 255, rawValues[(i * 3) + 2] / 255,
1.0);
ColorSquare cs = new ColorSquare(colors[i]);
squares.add(cs);
}
for (ColorSquare square : squares) {
add(square, columnIndex, rowIndex);
columnIndex++;
if (columnIndex == NUM_OF_COLUMNS) {
columnIndex = 0;
rowIndex++;
}
}
setOnMouseDragged(new EventHandler() {
@Override
public void handle(MouseEvent t) {
if (!dragDetected) {
dragDetected = true;
mouseDragColor = colorPicker.getValue();
}
int xIndex = (int)(t.getX()/16.0);
int yIndex = (int)(t.getY()/16.0);
int index = xIndex + yIndex*12;
if (index < NUM_OF_COLUMNS*NUM_OF_ROWS) {
colorPicker.setValue((Color) squares.get(index).rectangle.getFill());
updateSelection(colorPicker.getValue());
}
}
});
addEventHandler(MouseEvent.MOUSE_RELEASED, new EventHandler() {
@Override
public void handle(MouseEvent t) {
if(colorPickerGrid.getBoundsInLocal().contains(t.getX(), t.getY())) {
updateSelection(colorPicker.getValue());
colorPicker.fireEvent(new ActionEvent());
colorPicker.hide();
} else {
// restore color as mouse release happened outside the grid.
if (mouseDragColor != null) {
colorPicker.setValue(mouseDragColor);
updateSelection(mouseDragColor);
}
}
dragDetected = false;
}
});
}
public List getSquares() {
return squares;
}
double[] rawValues = {
255, 255, 255, // first row
242, 242, 242,
230, 230, 230,
204, 204, 204,
179, 179, 179,
153, 153, 153,
128, 128, 128,
102, 102, 102,
77, 77, 77,
51, 51, 51,
26, 26, 26,
0, 0, 0,
0, 51, 51, // second row
0, 26, 128,
26, 0, 104,
51, 0, 51,
77, 0, 26,
153, 0, 0,
153, 51, 0,
153, 77, 0,
153, 102, 0,
153, 153, 0,
102, 102, 0,
0, 51, 0,
26, 77, 77, // third row
26, 51, 153,
51, 26, 128,
77, 26, 77,
102, 26, 51,
179, 26, 26,
179, 77, 26,
179, 102, 26,
179, 128, 26,
179, 179, 26,
128, 128, 26,
26, 77, 26,
51, 102, 102, // fourth row
51, 77, 179,
77, 51, 153,
102, 51, 102,
128, 51, 77,
204, 51, 51,
204, 102, 51,
204, 128, 51,
204, 153, 51,
204, 204, 51,
153, 153, 51,
51, 102, 51,
77, 128, 128, // fifth row
77, 102, 204,
102, 77, 179,
128, 77, 128,
153, 77, 102,
230, 77, 77,
230, 128, 77,
230, 153, 77,
230, 179, 77,
230, 230, 77,
179, 179, 77,
77, 128, 77,
102, 153, 153, // sixth row
102, 128, 230,
128, 102, 204,
153, 102, 153,
179, 102, 128,
255, 102, 102,
255, 153, 102,
255, 179, 102,
255, 204, 102,
255, 255, 77,
204, 204, 102,
102, 153, 102,
128, 179, 179, // seventh row
128, 153, 255,
153, 128, 230,
179, 128, 179,
204, 128, 153,
255, 128, 128,
255, 153, 128,
255, 204, 128,
255, 230, 102,
255, 255, 102,
230, 230, 128,
128, 179, 128,
153, 204, 204, // eigth row
153, 179, 255,
179, 153, 255,
204, 153, 204,
230, 153, 179,
255, 153, 153,
255, 179, 128,
255, 204, 153,
255, 230, 128,
255, 255, 128,
230, 230, 153,
153, 204, 153,
179, 230, 230, // ninth row
179, 204, 255,
204, 179, 255,
230, 179, 230,
230, 179, 204,
255, 179, 179,
255, 179, 153,
255, 230, 179,
255, 230, 153,
255, 255, 153,
230, 230, 179,
179, 230, 179,
204, 255, 255, // tenth row
204, 230, 255,
230, 204, 255,
255, 204, 255,
255, 204, 230,
255, 204, 204,
255, 204, 179,
255, 230, 204,
255, 255, 179,
255, 255, 204,
230, 230, 204,
204, 255, 204
};
@Override protected double computePrefWidth(double height) {
return (SQUARE_SIZE + 1)*12;
}
@Override protected double computePrefHeight(double width) {
return (SQUARE_SIZE + 1)*10;
}
}
}