/**
* Warlock, the open-source cross-platform game client
*
* Copyright 2008, Warlock LLC, and individual contributors as indicated
* by the @authors tag.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package cc.warlock.rcp.ui;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ExtendedModifyEvent;
import org.eclipse.swt.custom.ExtendedModifyListener;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import cc.warlock.core.client.ICompass;
import cc.warlock.core.client.IPropertyListener;
import cc.warlock.core.client.ICompass.DirectionType;
import cc.warlock.rcp.ui.style.CompassTheme;
/**
* This is our custom compass that is drawn on top of the text widget and is movable like a normal window (within the text area for now).
* @author marshall
*/
public class WarlockCompass implements PaintListener, MouseMoveListener, MouseListener, IPropertyListener<ICompass> {
private StyledText text;
private boolean dragging = false;
private Point originalPosition = new Point(-1,-1), startedDraggingFrom = new Point(-1,-1);
private int x = -1, y = -1, rightDiff, bottomDiff;
private Cursor moveCursor;
private CompassTheme theme;
private ICompass compass;
private Image compassImage = WarlockSharedImages.getImage(WarlockSharedImages.IMG_COMPASS_SMALL_MAIN);
private Rectangle compassBounds = compassImage.getBounds();
public WarlockCompass (StyledText text, CompassTheme theme)
{
this.text = text;
this.theme = theme;
moveCursor = new Cursor(text.getDisplay(), SWT.CURSOR_HAND);
compassImage = theme.getMainImage();
compassBounds = compassImage.getBounds();
text.addPaintListener(this);
text.addMouseListener(this);
text.addMouseMoveListener(this);
text.addControlListener(new ControlListener () {
public void controlMoved(ControlEvent e) {}
public void controlResized(ControlEvent e) {
textResized(e);
}
});
text.getVerticalBar().addSelectionListener(new SelectionListener () {
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
public void widgetSelected(SelectionEvent e) {
redraw();
}
});
text.addExtendedModifyListener(new ExtendedModifyListener() {
public void modifyText(ExtendedModifyEvent e) {
redraw();
}
});
}
public void paintControl(PaintEvent e) {
drawCompass(e.gc);
}
public void redraw ()
{
if (!this.text.isDisposed())
{
this.text.redraw(x, 0, compassBounds.width, text.getBounds().height, true);
}
// text.redraw();
}
private void drawCompass (GC gc)
{
if (x == -1)
setX(text.getClientArea().width - compassBounds.width - 5);
if (y == -1)
setY(text.getClientArea().height - compassBounds.height - 5);
gc.drawImage(compassImage, x, y);
if (compass != null)
{
for (DirectionType direction : DirectionType.values())
{
if (direction != DirectionType.None && compass.getDirections().contains(direction))
{
Point point = theme.getDirectionPosition(direction);
gc.drawImage(theme.getDirectionImage(direction), point.x + x, point.y + y);
}
}
} else {
// draw all "on" by default
for (DirectionType direction : DirectionType.values())
{
if (direction != DirectionType.None)
{
Point point = theme.getDirectionPosition(direction);
gc.drawImage(theme.getDirectionImage(direction), point.x + x, point.y + y);
}
}
}
}
private boolean insideCompass (int x, int y)
{
return (x >= this.x && x <= this.x+compassBounds.width
&& y >= this.y && y <= this.y+compassBounds.height);
}
private boolean boundsInsideText (int topX, int topY)
{
int bottomX = topX + compassBounds.width;
int bottomY = topY + compassBounds.height;
Rectangle textBounds = text.getBounds();
return textBounds.contains(bottomX, bottomY);
}
public void mouseDoubleClick(MouseEvent e) {}
public void mouseDown(MouseEvent e) {
if (insideCompass(e.x, e.y))
{
dragging = true;
originalPosition.x = x; originalPosition.y = y;
startedDraggingFrom.x = e.x; startedDraggingFrom.y = e.y;
}
}
public void mouseMove(MouseEvent e) {
if (dragging)
{
int newX = originalPosition.x + (e.x - startedDraggingFrom.x);
int newY = originalPosition.y + (e.y - startedDraggingFrom.y);
if (boundsInsideText(newX, newY))
{
setX(newX);
setY(newY);
text.redraw();
}
}
if (insideCompass(e.x, e.y))
{
text.setCursor(moveCursor);
}
}
public void propertyChanged(ICompass value) {
compass = value;
redraw();
}
protected void textResized (ControlEvent e)
{
Rectangle textBounds = text.getBounds();
if (x <= rightDiff)
{
redraw();
} else {
setX(textBounds.width - rightDiff);
}
if (y <= bottomDiff)
{
redraw();
} else {
setY(textBounds.height - bottomDiff);
}
}
public void mouseUp(MouseEvent e) {
dragging = false;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
this.rightDiff = text.getBounds().width - x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
this.bottomDiff = text.getBounds().height - y;
}
public ICompass getCompass() {
return compass;
}
}