Spoken too early, obviously the location of the component is also needed (tried to override it with the location of my GUIActor but it was too messy, delegation is clearly better).
BasicComponent:
Code:
/** The location in the X coordinate*/
protected int x;
/** The location in the Y coordinate*/
protected int y;
/**
* Create a new component
*
* @param container The container displaying this component
*/
public BasicComponent(GUIContext container) {
this.container = container;
input = container.getInput();
input.addPrimaryListener(this);
x = y = 0;
}
/**
* Moves the component.
*
* @param x X coordinate
* @param y Y coordinate
*/
public void setLocation(int x, int y) {
this.x = x;
this.y = y;
}
/**
* Returns the position in the X coordinate
* @return x
*/
public int getX() {
return x;
}
/**
* Returns the position in the Y coordinate
* @return y
*/
public int getY() {
return y;
}
TextField:
Code:
/** The width of the field */
private int width;
/** The height of the field */
private int height;
public TextField(GUIContext container, Font font, int x, int y, int width, int height, ComponentListener listener) {
super(container);
this.listener = listener;
this.font = font;
setLocation(x, y);
this.width = width;
this.height = height;
}
/**
* Get the width of the component
*
* @return The width of the component
*/
public int getWidth() {
return width;
}
/**
* Get the height of the component
*
* @return The height of the component
*/
public int getHeight() {
return height;
}
/**
* @see org.newdawn.slick.gui.BasicComponent#renderImpl(org.newdawn.slick.gui.GUIContext, org.newdawn.slick.Graphics)
*/
public void renderImpl(GUIContext container, Graphics g) {
g.setClip(x, y-1, width+1, height+1);
if (background != null) {
g.setColor(background);
g.fillRect(x, y, width, height);
}
if (border != null) {
g.setColor(border);
g.drawRect(x, y, width, height);
}
g.setColor(text);
Font temp = g.getFont();
int cpos = font.getWidth(value.substring(0, cursorPos));
int tx = 0;
if (cpos > width) {
tx = width - cpos - font.getWidth("_");
}
g.translate(tx+2,0);
g.setFont(font);
g.drawString(value, x+1, y+1);
if ((focus) && (visibleCursor)) {
g.drawString("_", x+1+cpos+2, y+1);
}
g.translate(-tx-2, 0);
g.clearClip();
if (focus) {
// key repeat handling
if (input.isKeyDown(Input.KEY_LEFT)) {
if (container.getTime() - repeatLeft > REPEAT_TIMER) {
repeatLeft = container.getTime();
if (cursorPos > 0) {
cursorPos--;
}
}
}
if (input.isKeyDown(Input.KEY_RIGHT)) {
if (container.getTime() - repeatRight > REPEAT_TIMER) {
repeatRight = container.getTime();
if (cursorPos < value.length()) {
cursorPos++;
}
}
}
if (input.isKeyDown(Input.KEY_BACK)) {
if (container.getTime() - repeatBack > REPEAT_TIMER) {
if ((cursorPos > 0) && (value.length() > 0)) {
if (cursorPos < value.length()) {
value = value.substring(0, cursorPos-1) + value.substring(cursorPos);
} else {
value = value.substring(0, cursorPos-1);
}
cursorPos--;
repeatBack = container.getTime();
}
}
}
}
}
/**
* @see org.newdawn.slick.gui.BasicComponent#mouseReleased(int, int, int)
*/
public void mouseReleased(int button, int x, int y) {
setFocus((x >= this.x) && (y >= this.y) && (x <= this.x + width)
&& (y <= this.y + height));
}
MouseOverArea:
Code:
/** The width of the field */
private int width;
/** The height of the field */
private int height;
/**
* Create a new mouse over area
*
* @param container The container displaying the mouse over area
* @param image The normalImage to display
* @param x The position of the area
* @param y the position of the area
* @param width The width of the area
* @param height The height of the area
* @param listener The listener to notify of events
*/
public MouseOverArea(GUIContext container, Image image, int x, int y, int width, int height, ComponentListener listener) {
super(container);
normalImage = image;
currentImage = image;
mouseOverImage = image;
mouseDownImage = image;
currentColor = normalColor;
this.listener = listener;
setLocation(x, y);
this.width = width;
this.height = height;
}
/**
* Get the width of the area
*
* @return The width of the area
*/
public int getWidth() {
return width;
}
/**
* Get the height of the area
*
* @return The height of the area
*/
public int getHeight() {
return height;
}
/**
* @see org.newdawn.slick.gui.BasicComponent#renderImpl(org.newdawn.slick.gui.GUIContext,
* org.newdawn.slick.Graphics)
*/
public void renderImpl(GUIContext container, Graphics g) {
mouseDown = input.isMouseButtonDown(0);
int mX = input.getMouseX(), mY = input.getMouseY();
updateImage((mX >= x) && (mY >= y) && (mX <= x + width)
&& (mY <= y + height));
if (currentImage != null) {
int xp = x + ((width - currentImage.getWidth()) / 2);
int yp = y + ((height - currentImage.getHeight()) / 2);
currentImage.draw(xp, yp, currentColor);
} else {
g.setColor(currentColor);
g.fillRect(x, y, width, height);
}
}
(Erased rect in MouseOverArea and area in TextField, because they aren't needed anymore. Another alternative is making abstract setLocation, getX and getY and using the Rectangle in every subclass to store the location as well... just realized it. ^_^U Don't want to expose the area itself in BasicComponent because I'm adding a TextMenu where you set a Font and an array of Strings and the width and height adjust accordingly)
Nevertheless, with these changes we have complete control of the GUI elements and we can arrange them, move them, make composites, etc. in a really easy way.
Anyone with me? Please?
Pretty please covered in sugar?
