package pl.touk.tola.gwt.client.widgets; import com.extjs.gxt.ui.client.event.Events; import com.extjs.gxt.ui.client.event.Listener; import com.extjs.gxt.ui.client.event.FieldEvent; import com.extjs.gxt.ui.client.event.SelectionListener; import com.extjs.gxt.ui.client.event.ColorPaletteEvent; import com.extjs.gxt.ui.client.widget.Label; import com.extjs.gxt.ui.client.widget.ColorPalette; import com.extjs.gxt.ui.client.widget.HorizontalPanel; import com.extjs.gxt.ui.client.widget.button.Button; import com.extjs.gxt.ui.client.widget.form.TextField; import com.extjs.gxt.ui.client.widget.form.AdapterField; /** * Bindable color picker form field. * * @author Tomasz Przybysz <tpr@touk.pl> * * @see com.extjs.gxt.ui.client.widget.form.AdapterField * @see com.extjs.gxt.ui.client.widget.ColorPalette * @see com.extjs.gxt.ui.client.widget.menu.ColorMenu */ public class ColorPickerField extends AdapterField { public static String DEFAULT_LABEL = "Kolor"; final ColorMenu colorMenu; final TextField colorView; final Button selectButton; /** * Creates field with default colors palette. */ public ColorPickerField() { super( new HorizontalPanel() ); setFieldLabel( DEFAULT_LABEL ); setFireChangeEventOnSetValue( true ); colorMenu = createColorMenu(); colorView = createColorView(); selectButton = createSelectButton(); addComponents(); addListener( Events.Change, createFieldChangeListener() ); } /** * Creates field with custom colors palette. * * @param colors colors values in hex format without leading '#' */ public ColorPickerField( String... colors ) { this(); colorMenu.getColorPalette().setColors( colors ); } /** * Returns color in hex format. * * @return color hex value without leading '#' */ @Override public String getValue() { return (String) super.getValue(); } /** * Sets color in hex format. * * @param colorHex color hex value without leading '#' * @throws IllegalArgumentException if color is not defined in field's palette */ public void setValue( String colorHex ) { colorHex = colorHex.toUpperCase(); if (!isColorInPalette( colorHex )) { throw new IllegalArgumentException( "Color [" + colorHex + "] not in palette: " ); } super.setValue( colorHex ); } /** * Alias of {@link #getValue()}. */ public String getColor() { return getValue(); } /** * Alias of {@link #setValue(java.lang.String)}. */ public void setColor( String colorHex ) { setValue( colorHex ); } /** * Checks whether color is defined in field's palette. * * @param colorHex hex color value without leading '#' * @return true if color in palette, false otherwise */ public boolean isColorInPalette( String colorHex ) { String[] colors = colorMenu.getColorPalette().getColors(); for (String paletteColor : colors) { if (paletteColor.equalsIgnoreCase( colorHex )) { return true; } } return false; } private void addComponents() { HorizontalPanel container = (HorizontalPanel) this.getWidget(); container.add( colorView ); container.add( new Label( "  " ) ); container.add( selectButton ); } private TextField<String> createColorView() { TextField<String> field = new TextField<String>() { @Override public void setValue( String value ) { input.setStyleAttribute( "background", '#' + value ); } }; field.setWidth( 25 ); field.setReadOnly( true ); return field; } private ColorMenu createColorMenu() { ColorMenu menu = new ColorMenu(); menu.getColorPalette().addListener( Events.Select, createColorPaletteSelectionListener() ); return menu; } private Listener createFieldChangeListener() { return new Listener<FieldEvent>() { @Override public void handleEvent( FieldEvent fe ) { String color = String.valueOf( fe.getValue() ); colorMenu.getColorPalette().setValue( color ); colorView.setValue( color ); } }; } private SelectionListener createColorPaletteSelectionListener() { return new SelectionListener<ColorPaletteEvent>() { @Override public void componentSelected( ColorPaletteEvent ce ) { String color = ce.getColor(); ColorPickerField.this.setValue( color ); } }; } private Button createSelectButton() { Button btn = new Button( "wybierz" ); btn.setMenu( colorMenu ); return btn; } } /** * ColorPalette bug fix for GXT version 2.1.1 (and following I suppose). * * Bug occurs when setValue(String) method is used after previously selecting color * with mouse on ColorPalette. Problem is the color selected with mouse doesn't * deselect visually (still looks like "clicked" despite ColorPalette value changed). * * @author Tomasz Przybysz <tpr@touk.pl> * * @see com.extjs.gxt.ui.client.widget.ColorPalette */ class ColorMenu extends com.extjs.gxt.ui.client.widget.menu.ColorMenu { public ColorMenu() { super(); palette = createPatchedPalette(); removeAll(); add(palette); } private ColorPalette createPatchedPalette() { return new ColorPalette() { @Override public void setValue( String value ) { if (value == null || value.length() != 6) { // String with value "null" gets in here out of nowhere o_O return; } if (rendered) { select( value ); } else { super.setValue( value ); } } }; } }