/**************************************************************************
* Copyright (c) 2007, 2008 Gregory Jordan
*
* This file is part of PhyloWidget.
*
* PhyloWidget is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* PhyloWidget 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with PhyloWidget. If not, see <http://www.gnu.org/licenses/>.
*/
package org.andrewberman.ui.menu;
import java.awt.Cursor;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import org.andrewberman.ui.Point;
import org.andrewberman.ui.UIUtils;
import processing.core.PApplet;
import processing.core.PFont;
public class CheckBox extends MenuItem
{
public final static float CHECKBOX_SIZE = .8f;
private boolean value;
private Field field;
private Method method;
private Object methodObj;
private Object fieldObj;
private boolean useReflection;
private float tWidth, nWidth, nOffsetX, nHeight, nOffsetY;
@Override
public boolean getCloseOnAction()
{
return false;
}
public void setProperty(Object obj, String prop)
{
// First try to set the method call if it exists.
try {
String methodName = "set"+upperFirst(prop);
Method m = obj.getClass().getMethod(methodName,Boolean.TYPE);
setMethodCall(obj, methodName);
return;
} catch (Exception e)
{
// e.printStackTrace()
}
try
{
field = obj.getClass().getField(prop);
fieldObj = obj;
useReflection = true;
} catch (Exception e)
{
// e.printStackTrace();
field = null;
throw new RuntimeException();
}
}
static private String upperFirst(String s)
{
String sub = s.substring(0, 1).toUpperCase();
return sub + s.substring(1);
}
public void setMethodCall(Object obj, String meth)
{
try {
method = obj.getClass().getMethod(meth,Boolean.TYPE);
methodObj = obj;
useReflection = true;
} catch (Exception e)
{
// e.printStackTrace();
method = null;
methodObj = null;
useReflection = false;
throw new RuntimeException();
}
}
public void setValue(String s)
{
setVal(Boolean.parseBoolean(s));
}
void setVal(boolean value)
{
this.value = value;
if (useReflection)
{
try
{
if (field != null)
field.setBoolean(fieldObj, value);
} catch (Exception e)
{
e.printStackTrace();
}
try
{
if (method != null)
method.invoke(methodObj, value);
} catch (Exception e)
{
e.printStackTrace();
}
}
}
public boolean getValue()
{
return value;
}
public void drawMyself()
{
super.drawMyself();
float px = getStyle().getF("f.padX");
float py = getStyle().getF("f.padY");
float curX = x + px;
MenuUtils.drawLeftText(this, getName() + ":", curX);
// curX += tWidth;
curX = getX() + getWidth() - px - nWidth;
if (getState() == MenuItem.UP)
{
menu.buff.strokeWeight(0.5f);
menu.buff.stroke(100);
menu.buff.noFill();
menu.buff.rect(curX, y+nOffsetY, nWidth, nHeight);
// MenuUtils.drawBlankRect(this, curX, y+nOffsetY, nWidth, nHeight);
} else
{
if (shouldPerformFill())
MenuUtils.drawSingleGradientRect(this, curX, y+nOffsetY, nWidth, nHeight,0);
}
/*
* update the "value" object using Reflection.
*/
try
{
if (field != null)
value = field.getBoolean(fieldObj);
} catch (Exception e)
{
useReflection = false;
e.printStackTrace();
}
/*
* Draw the check mark, if necessary.
*/
if (value)
{
drawCheckMark();
}
}
private void drawCheckMark()
{
float w = nWidth * .75f;
float h = nHeight * .75f;
float x0 = x + nOffsetX + (nWidth - w)/2f;
float y0 = y + nOffsetY + (nHeight - h)/2f;
menu.canvas.strokeWeight(nHeight/8f);
menu.canvas.stroke(0);
menu.canvas.line(x0+w*.2f, y0+h*.6f,
x0+w*.5f, y0+h*.9f);
menu.canvas.line(x0+w*.5f, y0+h*.9f,
x0+w*.8f,y0+h*.2f);
}
protected void calcPreferredSize()
{
super.calcPreferredSize();
PFont font = getStyle().getFont("font");
float fontSize = getStyle().getF("f.fontSize");
float px = getStyle().getF("f.padX");
float py = getStyle().getF("f.padY");
/*
* For the height, let's use the height of some capital letters.
*/
float tHeight = UIUtils.getTextHeight(menu.buff, font,
fontSize, "XYZ", true);
/*
* Calculate the text rectangle size.
*/
if (getName().length() > 0)
{
tWidth = UIUtils.getTextWidth(menu.buff, font,
fontSize, getName() + ":", true);
tWidth += px;
}
setHeight(tHeight + 2 * py);
nOffsetX = getWidth() - px - nWidth;
nHeight = tHeight * CHECKBOX_SIZE;
nWidth = nHeight;
nOffsetY = (getHeight() - nHeight)/2f;
setWidth(px + tWidth + nWidth + px);
}
protected void getRect(Rectangle2D.Float rect, Rectangle2D.Float buff)
{
buff.setFrame(x, y, width, height);
Rectangle2D.union(rect, buff, rect);
super.getRect(rect, buff);
}
public void performAction()
{
setVal(!value);
super.performAction();
}
protected void visibleMouseEvent(MouseEvent e, Point tempPt)
{
super.visibleMouseEvent(e, tempPt);
if (!isEnabled())
return;
if (mouseInside)
{
menu.setCursor(Cursor.HAND_CURSOR);
}
switch (e.getID())
{
case (MouseEvent.MOUSE_PRESSED):
if (mouseInside)
{
// setVal(!value);
}
break;
case (MouseEvent.MOUSE_DRAGGED):
break;
case (MouseEvent.MOUSE_RELEASED):
break;
}
}
static RoundRectangle2D.Float buffRoundRect = new RoundRectangle2D.Float(0,
0, 0, 0, 0, 0);
protected boolean containsPoint(Point p)
{
float ro = getStyle().getF("f.roundOff");
buffRoundRect.setRoundRect(x, y, width, height, ro,
ro);
// buffRoundRect.setRoundRect(x + nOffsetX, y + nOffsetY, nWidth, nHeight,
// getStyle().roundOff, getStyle().roundOff);
return buffRoundRect.contains(p);
}
@Override
public void keyEvent(KeyEvent e)
{
super.keyEvent(e);
if (e.getID() != KeyEvent.KEY_PRESSED)
return;
switch (e.getKeyCode())
{
case (KeyEvent.VK_SPACE):
performAction();
break;
case (KeyEvent.VK_ENTER):
break;
}
}
}