package data;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import script.Script;
import bGUI.BEditor;
import bGUI.BGameCanvas;
/**
*
* @author Chidozie Nwobilor
*
*/
public class BShape implements BModelListener{
public static final int KNOB_SIZE = 10;
public static final Font DEFAULT_FONT = new Font("Dialog", Font.PLAIN, (int) 1.0);
public static final Point DEFAULT_START = new Point(0,0);
public static final int DEFAULT_HEIGHT = 100;
public static final int DEFAULT_WIDTH = 100;
private List<Point> knobs;
private BShapeModel model;
public BShape(){
setModel(new BShapeModel());
this.getModel().addListener(this);
setName("");
setText("");
setImageName("none");
setHidden(false);
setMovable(true);
setBounds(new Rectangle(DEFAULT_START.x, DEFAULT_START.y, DEFAULT_WIDTH, DEFAULT_HEIGHT));
knobs = new ArrayList<Point>();
getKnobs();
setFont(BShape.DEFAULT_FONT);
}
/**
* standard constructor except that the shape does not get added
* as a listener to the model
* @param model
* @param r
*/
public BShape(BShapeModel model, Rectangle r) {
setModel(model);
setName("");
setText("");
setImageName("");
setHidden(false);
setMovable(true);
setBounds(r);
knobs = new ArrayList<Point>();
getKnobs();
setFont(this.model.getFont());
}
/**
* sets the model for the shape class. MUST be called first before any changes are made
* @param shapeModel
*/
public void setModel(BShapeModel shapeModel) {
model = shapeModel;
}
public BShapeModel getModel(){
return model;
}
public void draw(Graphics g){
Shape clip = g.getClip();
Rectangle r = model.getBounds();
g.setClip(r);
if(model.getText().equals("")) DrawImage(g, r);
else DrawText(g, r);
g.setClip(clip);
}
private Font computeFont(Font f, Graphics g, Rectangle bounds){
double size = 1.0;
Font curr = f.deriveFont(f.getStyle(), (int)size);
Font prev = curr;
while(true){
FontMetrics fm = g.getFontMetrics(curr);
if(fm.getHeight() > bounds.height){
fm = g.getFontMetrics(prev);
bounds.height -= fm.getDescent();
return prev;
}
size = (size * 1.10) + 1;
prev = curr;
curr = f.deriveFont(f.getStyle(), (int)size);
}
}
private void DrawText(Graphics g, Rectangle r) {
Font f = computeFont(model.getFont(), g, r);
g.setColor(getColor());
g.setFont(f);
g.drawString(model.getText(), r.x, r.y + r.height);
}
private void DrawImage(Graphics g, Rectangle r) {
Image image = model.getData().getImage(getImageName());
if(getImageName().equals("") || image == null){
g.setColor(model.getColor());
g.fillRect(r.x, r.y, r.width, r.height);
}else{
g.drawImage(image, r.x, r.y, r.width, r.height, null);
}
}
public void move(Point delta){
if(getMovable()) model.move(delta);
}
public void move(int x, int y){
this.move(new Point(x, y));
}
public void resize(Point anchor, Point newPoint){
if(getMovable()) model.adjust(anchor, newPoint);
}
/**
* returns the corners of the bounds of the object
* @return list of Points
*/
public List<Point> getKnobs(){
knobs.clear();
Rectangle r = model.getBounds();
knobs.add(new Point(r.x, r.y));
knobs.add(new Point(r.x + r.width, r.y));
knobs.add(new Point(r.x, r.y + r.height));
knobs.add(new Point(r.x + r.width, r.y + r.height));
return knobs;
}
/**
* currently returns the anchor point for the given point. Does not determine if point is in knob
* or not
* @param pt
* @return anchor point
*/
public Point getAnchorForPoint(Point pt){
Point result = null;
getKnobs();
if(InKnobRegion(pt, knobs.get(0))) result = knobs.get(3);
else if(InKnobRegion(pt, knobs.get(1))) result = knobs.get(2);
else if(InKnobRegion(pt, knobs.get(2))) result = knobs.get(1);
else if(InKnobRegion(pt, knobs.get(3))) result = knobs.get(0);
return result;
}
private boolean InKnobRegion(Point pt, Point center) {
Rectangle r = new Rectangle(center.x - BShape.KNOB_SIZE / 2, center.y - BShape.KNOB_SIZE / 2, BShape.KNOB_SIZE, BShape.KNOB_SIZE);
return r.contains(pt);
}
public Rectangle getBigBounds(){
Rectangle r = model.getBounds();
r.height += KNOB_SIZE;
r.width += KNOB_SIZE;
r.x -= KNOB_SIZE / 2;
r.y -= KNOB_SIZE / 2;
return r;
}
public Rectangle getBounds(){
return model.getBounds();
}
public void setBounds(Rectangle newBounds){
model.setBounds(newBounds);
}
/**
* @param name the name to set
*/
public void setName(String name) {
model.setName(name);
}
/**
* @return the name
*/
public String getName() {
return model.getName();
}
/**
* @param text the text to set
*/
public void setText(String text) {
model.setText(text);
}
/**
* @return the text
*/
public String getText() {
return model.getText();
}
/**
* @param imageName the imageName to set
*/
public void setImageName(String imageName) {
model.setImageName(imageName);
}
/**
* @return the imageName
*/
public String getImageName() {
return model.getImageName();
}
/**
* @param hidden the hidden to set
*/
public void setHidden(boolean hidden) {
model.setHidden(hidden);
}
/**
* @return the hidden
*/
public boolean getHidden() {
return model.getHidden();
}
/**
* sets whether or not the shape is movable
* @param movable the movable to set
*/
public void setMovable(boolean movable) {
model.setMovable(movable);
}
/**
* @return the movable
*/
public boolean getMovable() {
return model.getMovable();
}
/**
* @param font the font to set
*/
public void setFont(Font font) {
model.setFont(font);
}
/**
* @return the font
*/
public Font getFont() {
return model.getFont();
}
/**
* sets the bold on the font on and off
* @param makeBold
*/
public void setFontBold(boolean makeBold){
Font font = model.getFont();
if(makeBold){
if(font.isItalic()){
setFont(font.deriveFont(Font.BOLD + Font.ITALIC));
}else{
setFont(font.deriveFont(Font.BOLD));
}
}else{
if(font.isItalic()){
setFont(font.deriveFont(Font.ITALIC));
}else{
setFont(font.deriveFont(Font.PLAIN));
}
}
}
/**
* sets the italic on the font on and off
* @param makeItalic
*/
public void setFontItalics(boolean makeItalic){
Font font = model.getFont();
if(makeItalic){
if(font.isBold()){
setFont(font.deriveFont(Font.BOLD + Font.ITALIC));
}else{
setFont(font.deriveFont(Font.ITALIC));
}
}else{
if(font.isBold()){
setFont(font.deriveFont(Font.BOLD));
}else{
setFont(font.deriveFont(Font.PLAIN));
}
}
}
/**
* returns a map of scripts
* @return model scripts
*/
public Map<String, String> getScript(){
return model.getScripts();
}
/**
* adds script to the model. cannot add scripts with same triggers to the map. last one added
* will count
* @param script
*/
public void addScript(String script){
model.addScript(script);
}
/**
* creates a scaled copy of the shape so that the shape retains it's original bounds and draws
* that instead.
* @param shape
*/
public static BShape drawScaled(BShape shape, Graphics g, Rectangle r){
Rectangle scaledBounds = GetScaledBounds(r, shape.getBounds());
BShape temp = new BShape(shape.getModel().clone(), scaledBounds);
temp.draw(g);
return temp;
}
public static BShape getScaled(BShape shape, Rectangle r){
Rectangle scaledBounds = GetScaledBounds(r, shape.getBounds());
BShape temp = new BShape(shape.getModel().clone(), scaledBounds);
temp.setColor(shape.getColor());
temp.setFont(shape.getFont());
temp.setHidden(shape.getHidden());
temp.setImageName(shape.getImageName());
temp.setName(shape.getName());
temp.setText(shape.getText());
return temp;
}
public static Rectangle GetScaledBounds(BShape shape, Rectangle r){
return GetScaledBounds(r, shape.getBounds());
}
/*
* (non-javadoc)
* returns a scaled version of the original bounds
*/
private static Rectangle GetScaledBounds(Rectangle r, Rectangle origBounds) {
double scale = (double)r.height/ origBounds.height;
return new Rectangle(r.x, r.y, ((int) (origBounds.width * scale)), r.height);
}
public void modelChanged(BShapeModel model) {
// TODO Auto-generated method stub
}
public void setFont(String fontname){
Font font = new Font(fontname, Font.PLAIN, (int) 1.0);
model.setFont(font);
}
public void setColor(Color color){
model.setColor(color);
}
public Color getColor(){
return model.getColor();
}
public void doScript(String s, BGameCanvas canvas) {
String script = this.getScript().get(s);
if(script != null) Script.execute(script, canvas);
}
/**
* determines whether on not the selected shape can be dropped on the Shape
* @param selected
* @return
*/
public boolean canRecieve(BShape selected) {
return model.canRecieve(selected);
}
public void removeListener(BModelListener l) {
model.removeListener(l);
}
public void addListener(BModelListener l) {
model.addListener(l);
}
public String toString() {
return model.toString();
}
public String getScriptBlock(){
return model.getScriptBlock();
}
public BShape clone(){
BShape clone = new BShape();
clone.setBounds((Rectangle) this.getBounds().clone());
clone.setColor(this.getColor());
clone.setFont(this.getFont());
clone.setHidden(getHidden());
clone.setMovable(this.getMovable());
clone.setImageName(this.getImageName());
clone.setModel(this.model.clone());
clone.setText(getText());
clone.setName(getName());
return clone;
}
public boolean listenerContains(BModelListener l) {
return model.containsListener(l);
}
}