/**
* Copyright 2014 the staff of 52°North Initiative for Geospatial Open
* Source Software GmbH in their free time
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package spare.n52.yadarts.layout.board;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import spare.n52.yadarts.entity.PointEvent;
import spare.n52.yadarts.themes.Theme;
public class BoardView extends Composite {
private static final Logger logger = LoggerFactory.getLogger(BoardView.class);
private static final int MAX_M_SIZE = 1000;
private static final int MAX_LO_SIZE = 750;
private final Color dartColor = new Color(getDisplay(), new RGB(255, 0, 255));
private Image imageM;
private Image imageHi;
private Image imageLo;
private Label theBoard;
private Image background;
private List<DynamicPolarCoordinate> arrows = new ArrayList<>();
private Point currentCenter;
private int currentRadius;
private int currentDartSize;
public BoardView(final Composite parent, int style) {
super(parent, style);
this.setLayout(new FillLayout());
try {
imageM = Theme.getCurrentTheme().getBoardM(getDisplay());
imageHi = Theme.getCurrentTheme().getBoardHi(getDisplay());
imageLo = Theme.getCurrentTheme().getBoardLo(getDisplay());
background = Theme.getCurrentTheme().getBackground(getDisplay());
} catch (FileNotFoundException e1) {
logger.warn(e1.getMessage(), e1);
throw new IllegalStateException("The theme is not correctly configured");
}
theBoard = new Label(this, SWT.NONE);
theBoard.setBackgroundImage(background);
theBoard.setImage(imageM);
theBoard.setAlignment(SWT.CENTER);
theBoard.addControlListener(new ControlAdapter() {
@Override
public void controlResized(ControlEvent e) {
super.controlResized(e);
Rectangle newBounds = theBoard.getBounds();
int newWidthHeight = Math
.min(newBounds.height, newBounds.width);
theBoard.setImage(resize(newWidthHeight,
newWidthHeight));
parent.layout();
}
});
theBoard.addPaintListener(new PaintListener() {
@Override
public void paintControl(PaintEvent e) {
logger.debug("current center is {}", currentCenter);
for (DynamicPolarCoordinate c : arrows) {
drawDartAt(c.calculatePoint(currentCenter, currentRadius), e.gc);
}
}
});
}
private Image resize(int width, int height) {
Image image;
if (width > MAX_M_SIZE) {
image = imageHi;
}
else if (width > MAX_LO_SIZE) {
image = imageM;
}
else {
image = imageLo;
}
Image scaled = new Image(getDisplay(), width, height);
GC gc = new GC(scaled);
try {
gc.setAntialias(SWT.ON);
gc.setInterpolation(SWT.HIGH);
}
catch (SWTException e) {
logger.warn(e.getMessage());
logger.debug(e.getMessage(), e);
}
gc.drawImage(image, 0, 0, image.getBounds().width,
image.getBounds().height, 0, 0, width, height);
updateScaleRatio(scaled);
gc.dispose();
return scaled;
}
private void updateScaleRatio(Image image) {
this.currentCenter = new Point(theBoard.getBounds().width / 2, theBoard.getBounds().height / 2);
this.currentRadius = image.getBounds().width / 2;
this.currentDartSize = this.currentRadius / 12;
}
public void removeLastHit() {
getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
if (arrows != null && arrows.size() > 0) {
arrows.remove(arrows.size()-1);
theBoard.redraw();
}
}
});
}
public void onPointEvent(final PointEvent event) {
getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
processNumberHit(event);
}
});
}
private void processNumberHit(PointEvent event) {
DynamicPolarCoordinate coordinate = new DynamicPolarCoordinate(event);
coordinate.setDeviation(calculateDeviation(event));
this.arrows.add(coordinate);
theBoard.redraw();
}
private Deviation calculateDeviation(PointEvent event) {
if (this.arrows.size() == 0) {
return new Deviation();
}
List<DynamicPolarCoordinate> inSameField = new ArrayList<>(2);
for (DynamicPolarCoordinate c : this.arrows) {
if (sameField(event, c.getEvent())) {
inSameField.add(c);
}
}
if (inSameField.isEmpty()) {
return new Deviation();
}
else {
return calculateFieldDependentDeviation(event, inSameField);
}
}
private Deviation calculateFieldDependentDeviation(PointEvent event,
List<DynamicPolarCoordinate> inSameField) {
if (event.getMultiplier() == 1) {
if (event.getBaseNumber() == 25) {
return HitAreaConstants.BULLSEYE_DEVIATION[inSameField.size()-1];
}
if (event.isOuterRing()) {
return HitAreaConstants.OUTER_RING_DEVIATION[inSameField.size()-1];
}
else {
return HitAreaConstants.INNER_RING_DEVIATION[inSameField.size()-1];
}
}
else if (event.getMultiplier() == 2) {
if (event.getBaseNumber() == 25) {
return HitAreaConstants.DOUBLE_BULLSEYE_DEVIATION[inSameField.size()-1];
}
return HitAreaConstants.DOUBLE_DEVIATION[inSameField.size()-1];
}
else if (event.getMultiplier() == 3) {
return HitAreaConstants.TRIPLE_DEVIATION[inSameField.size()-1];
}
return new Deviation();
}
private boolean sameField(PointEvent a, PointEvent b) {
return a.getBaseNumber() == b.getBaseNumber()
&& a.getMultiplier() == b.getMultiplier()
&& a.isOuterRing() == b.isOuterRing();
}
private void drawDartAt(Point point, GC gc) {
gc.setForeground(dartColor);
gc.setLineWidth(3);
gc.drawLine(point.x-currentDartSize, point.y-currentDartSize, point.x+currentDartSize, point.y+currentDartSize);
gc.drawLine(point.x-currentDartSize, point.y+currentDartSize, point.x+currentDartSize, point.y-currentDartSize);
}
public void removeAllArrows() {
getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
arrows.clear();
theBoard.redraw();
}
});
}
}