/*
* Copyright 2000-2016 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.ui.components.colorpicker;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomField;
/**
* A component that represents color selection history within a color picker.
*
* @since 7.0.0
*/
public class ColorPickerHistory extends CustomField<Color> {
private static final String STYLENAME = "v-colorpicker-history";
private static final int ROWS = 4;
private static final int COLUMNS = 15;
/** Temporary color history for when the component is detached. */
private final ArrayBlockingQueue<Color> tempHistory = new ArrayBlockingQueue<>(
ROWS * COLUMNS);
@Override
protected Component initContent() {
setPrimaryStyleName(STYLENAME);
ColorPickerGrid grid = new ColorPickerGrid(ROWS, COLUMNS);
grid.setWidth("100%");
grid.setPosition(0, 0);
grid.addValueChangeListener(
event -> fireEvent(new ValueChangeEvent<>(this,
event.getOldValue(), event.isUserOriginated())));
return grid;
}
@Override
protected ColorPickerGrid getContent() {
return (ColorPickerGrid) super.getContent();
}
@Override
public void attach() {
super.attach();
createColorHistoryIfNecessary();
}
private void createColorHistoryIfNecessary() {
List<Color> tempColors = new ArrayList<>(tempHistory);
if (getSession().getAttribute("colorPickerHistory") == null) {
getSession().setAttribute("colorPickerHistory",
new ArrayBlockingQueue<Color>(ROWS * COLUMNS));
}
for (Color color : tempColors) {
setValue(color);
}
tempHistory.clear();
}
@SuppressWarnings("unchecked")
private ArrayBlockingQueue<Color> getColorHistory() {
if (isAttached()) {
Object colorHistory = getSession()
.getAttribute("colorPickerHistory");
if (colorHistory instanceof ArrayBlockingQueue<?>) {
return (ArrayBlockingQueue<Color>) colorHistory;
}
}
return tempHistory;
}
@Override
public void setHeight(String height) {
super.setHeight(height);
getContent().setHeight(height);
}
@Override
public Color getValue() {
return getColorHistory().peek();
}
@Override
protected void doSetValue(Color color) {
ArrayBlockingQueue<Color> colorHistory = getColorHistory();
// Check that the color does not already exist
boolean exists = false;
Iterator<Color> iter = colorHistory.iterator();
while (iter.hasNext()) {
if (color.equals(iter.next())) {
exists = true;
break;
}
}
// If the color does not exist then add it
if (!exists) {
if (!colorHistory.offer(color)) {
colorHistory.poll();
colorHistory.offer(color);
}
}
List<Color> colorList = new ArrayList<>(colorHistory);
// Invert order of colors
Collections.reverse(colorList);
// Move the selected color to the front of the list
Collections.swap(colorList, colorList.indexOf(color), 0);
// Create 2d color map
Color[][] colors = new Color[ROWS][COLUMNS];
iter = colorList.iterator();
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
if (iter.hasNext()) {
colors[row][col] = iter.next();
} else {
colors[row][col] = Color.WHITE;
}
}
}
getContent().setColorGrid(colors);
getContent().markAsDirty();
}
/**
* Gets the history.
*
* @return the history
*/
public List<Color> getHistory() {
ArrayBlockingQueue<Color> colorHistory = getColorHistory();
Color[] array = colorHistory.toArray(new Color[colorHistory.size()]);
return Collections.unmodifiableList(Arrays.asList(array));
}
/**
* Checks if the history contains given color.
*
* @param c
* the color
*
* @return true, if successful
*/
public boolean hasColor(Color c) {
return getColorHistory().contains(c);
}
}