/*********************************************************************************
* TotalCross Software Development Kit *
* Copyright (C) 2000-2012 SuperWaba Ltda. *
* All Rights Reserved *
* *
* This library and virtual machine 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. *
* *
* This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 *
* A copy of this license is located in file license.txt at the root of this *
* SDK or can be downloaded here: *
* http://www.gnu.org/licenses/lgpl-3.0.txt *
* *
*********************************************************************************/
package totalcross.ui.dialog;
import totalcross.sys.*;
import totalcross.ui.*;
import totalcross.ui.event.*;
import totalcross.ui.gfx.*;
import totalcross.ui.image.*;
/** Shows a color dialog that can be used to select a color. There are several ways to choose a color:
* <ul>
* <li> Using a color matrix
* <li> Using a websafe palette
* <li> Writting the red, green and blue components
* <li> Writting the color in hexdecimal.
* </ul>
* Here's a sample code:
* <pre>
* ColorChooserBox ccb = new ColorChooserBox(getBackColor());
* ccb.popup();
* if (ccb.choosenColor != -1) // user pressed cancel?
* {
* int color = ccb.choosenColor; // no, color was selected
* }
* </pre>
* @since TotalCross
*/
public class ColorChooserBox extends Window implements PenListener
{
private Image colorMatrix;
private Graphics gcolors;
private ImageControl ic;
private ComboBox cbColors;
private Edit edR, edG, edB, edRGB;
private PushButtonGroup pbgNum,pbgAlpha,pbgAction;
private Container cColor;
private ColorList.Item colorItem;
private AlignedLabelsContainer alc;
private KeyEvent ke = new KeyEvent();
/** The choosen color or -1 if the user cancelled. */
public int choosenColor = -1;
public ColorChooserBox(int defaultColor)
{
super("Color Chooser", RECT_BORDER);
choosenColor = defaultColor;
transitionEffect = Settings.enableWindowTransitionEffects ? TRANSITION_OPEN : TRANSITION_NONE;
fadeOtherWindows = Settings.fadeOtherWindows;
uiAdjustmentsBasedOnFontHeightIsSupported = false;
setBackColor(UIColors.colorchooserboxBack);
setForeColor(UIColors.colorchooserboxFore);
setRect(LEFT,TOP,FILL,FILL);
}
public void initUI()
{
colorItem = new ColorList.Item(0);
int extra = Settings.screenHeight < 320 ? 0 : 8;
alc = new AlignedLabelsContainer(new String[]{"Palette: ","Red: ","Green: ","Blue: ","Hex: "});
alc.foreColors = new int[]{0xAA00AA, 0xAA0000, 0x007700, 0x0000AA, 0x222222};
add(alc, LEFT, TOP+2, WILL_RESIZE, WILL_RESIZE);
alc.add(cbColors = new ComboBox(new ColorList()),LEFT,alc.getLineY(0),PREFERRED,fmH+Edit.prefH);
alc.add(edR = new Edit("999"),LEFT, alc.getLineY(1));
alc.add(edG = new Edit("999"),LEFT, alc.getLineY(2));
alc.add(edB = new Edit("999"),LEFT, alc.getLineY(3));
alc.add(edRGB = new Edit("999999"),LEFT, alc.getLineY(4));
edR.setMode(Edit.KBD_NONE, true); edR.autoSelect = true;
edG.setMode(Edit.KBD_NONE, true); edG.autoSelect = true;
edB.setMode(Edit.KBD_NONE, true); edB.autoSelect = true;
edRGB.setMode(Edit.KBD_NONE, true); edRGB.autoSelect = true;
edRGB.setValidChars("01234567890ABCDEF");
edRGB.capitalise = Edit.ALL_UPPER;
alc.resize();
alc.resetSetPositions();
alc.setRect(RIGHT-2,KEEP,KEEP,KEEP); // right can't be used with WILL_RESIZE
addColorMatrix();
add(pbgNum = new PushButtonGroup(new String[]{"1","2","3","4","5","6","7","8","9","0"}, 2, 2), SAME, AFTER+4, SAME, PREFERRED+extra, alc);
pbgNum.setFocusLess(true);
pbgNum.setVisible(false);
add(pbgAlpha = new PushButtonGroup(new String[]{"A","B","C","D","E","F"}, 2, 1), SAME, AFTER+2, SAME, PREFERRED+extra/2);
pbgAlpha.setFocusLess(true);
pbgAlpha.setVisible(false);
add(pbgAction = new PushButtonGroup(new String[]{"Ok","Cancel"}, 2, 1), SAME, BOTTOM-2, SAME, PREFERRED+extra/2);
pbgAction.setBackColor(UIColors.colorchooserboxAction);
cColor = new Container();
cColor.setBorderStyle(BORDER_SIMPLE);
add(cColor,SAME,AFTER+extra,SAME,FIT-4,pbgAlpha);
colorChanged(choosenColor,-1,-1,-1);
}
private void addColorMatrix()
{
try
{
if (colorMatrix != null)
{
colorMatrix = null;
gcolors = null;
ic.removePenListener(this);
remove(ic);
ic = null;
}
Rect r = getClientRect();
colorMatrix = createColorMatrix(alc.getX()-5,r.height-4);
gcolors = colorMatrix.getGraphics();
add(ic = new ImageControl(colorMatrix), LEFT+2,TOP+2,colorMatrix.getWidth(),colorMatrix.getHeight());
ic.addPenListener(this);
}
catch (ImageException e)
{
e.printStackTrace();
unpop();
}
}
protected void reposition(boolean recursive)
{
super.reposition(recursive);
addColorMatrix();
}
public void onEvent(Event e)
{
switch (e.type)
{
case ControlEvent.PRESSED:
if (e.target == pbgAction)
switch (pbgAction.getSelectedIndex())
{
case 1: // cancel
choosenColor = -1; // no break
case 0:
unpop();
break;
}
else
if (e.target instanceof PushButtonGroup && _focus != null && _focus instanceof Edit)
{
String s = ((PushButtonGroup)e.target).getSelectedItem();
if (s != null)
{
ke.key = s.charAt(0);
ke.target = _focus;
_focus.onEvent(ke);
}
}
else
if (e.target == cbColors)
{
ColorList.Item it = (ColorList.Item)cbColors.getSelectedItem();
if (it != null)
colorChanged(it.value, -1,-1,-1);
}
else
if (e.target instanceof Edit)
{
int v = 0;
if (e.target == edR || e.target == edG || e.target == edB)
{
boolean err = false;
Edit ed = (Edit)e.target;
try
{
v = Convert.toInt(ed.getText());
if (v > 255)
err = true;
}
catch (InvalidNumberException e1)
{
err = true;
}
if (err)
{
v = 0;
ed.setText("0");
}
else
((Edit)e.target).setText(Convert.toString(v));
colorChanged(-1, e.target == edR ? v : -1, e.target == edG ? v : -1, e.target == edB ? v : -1);
if (err)
ed.setCursorPos(0,1);
}
else
if (e.target == edRGB)
{
try
{
String s = ((Edit)e.target).getText();
if (s.length() > 0)
{
v = (int)Convert.toLong(s, 16);
}
}
catch (InvalidNumberException e1)
{
}
colorChanged(v, -1,-1,-1);
}
}
break;
case ControlEvent.FOCUS_IN:
pbgAlpha.setVisible(e.target == edRGB);
pbgNum.setVisible(e.target == edRGB || e.target == edR || e.target == edG || e.target == edB);
break;
case ControlEvent.FOCUS_OUT:
if (e.target instanceof Edit)
{
pbgAlpha.setVisible(false);
pbgNum.setVisible(false);
}
break;
}
}
public void onPopup()
{
if (choosenColor != -1)
colorChanged(choosenColor,-1,-1,-1);
}
private void colorChanged(int rgb, int r, int g, int b)
{
if (rgb != -1)
choosenColor = rgb;
if (r == -1) r = Color.getRed(choosenColor);
if (g == -1) g = Color.getGreen(choosenColor);
if (b == -1) b = Color.getBlue(choosenColor);
if (rgb == -1)
{
rgb = choosenColor = (r << 16) | (g << 8) | b;
edRGB.setText(Convert.unsigned2hex(rgb,6).toUpperCase());
}
else edRGB.setText(Convert.toString(rgb,16).toUpperCase());
edR.setText(Convert.toString(r));
edG.setText(Convert.toString(g));
edB.setText(Convert.toString(b));
cColor.setBackColor(rgb);
// changes the title colors
setForeColor(rgb);
titleColor = Color.getBetterContrast(rgb, Color.BLACK, Color.WHITE);
colorItem.set(choosenColor);
int idx = cbColors.indexOf(colorItem);
cbColors.setSelectedIndex(idx);
repaintNow();
}
private static final int BIAS = 16;
private static final int ONE = 1<<BIAS;
private Image createColorMatrix(int w, int h) throws ImageException
{
Image img = new Image(w,h);
Graphics g = img.getGraphics();
w -= 2; // remove border from computation
h -= 2;
int hueInc = (360 << BIAS) / (h-1) / 360;
int satInc = (100 << BIAS) / (w-1) / 100;
int hue = 0;
int sat = 0;
for (int yy = 0; yy < h; yy++)
{
sat = 0;
for (int xx = w; --xx >= 0; sat += satInc)
{
g.foreColor = hsb2rgb(hue, sat);
g.setPixel(xx,yy);
}
hue += hueInc;
}
return img;
}
private int hsb2rgb(int ihue, int isat)
{
int red=255, green=255, blue=255;
if (isat != 0)
{
int df = ihue>>BIAS<<BIAS;
int h = (ihue - df) * 6;
int hf = h>>BIAS<<BIAS;
int f = h - hf;
int p = (255 * (ONE - isat)) >> BIAS;
int q = (255 * (ONE - (isat * f >> BIAS))) >> BIAS;
int t = (255 * (ONE - (isat * (ONE - f) >> BIAS))) >> BIAS;
switch (h>>BIAS)
{
case 0:
green = t;
blue = p;
break;
case 1:
red = q;
blue = p;
break;
case 2:
red = p;
blue = t;
break;
case 3:
red = p;
green = q;
break;
case 4:
red = t;
green = p;
break;
case 5:
green = p;
blue = q;
break;
}
}
return (red << 16) | (green << 8) | blue;
}
public void penDown(PenEvent e)
{
int c = gcolors.getPixel(e.x, e.y);
colorChanged(c, -1, -1, -1);
}
public void penUp(PenEvent e)
{
}
public void penDrag(DragEvent e)
{
penDown(e);
}
public void penDragStart(DragEvent e)
{
// TODO Auto-generated method stub
}
public void penDragEnd(DragEvent e)
{
// TODO Auto-generated method stub
}
}