package de.lighti.components.map;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.CrosshairState;
import org.jfree.chart.plot.PlotRenderingInfo;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYDotRenderer;
import org.jfree.chart.renderer.xy.XYItemRendererState;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import de.lighti.model.Statics;
/**
* The MapCanvasComponent renders different variations of the Dota2 minimap
* along with a series of markers. The component has a fixed size of 512x512.
*
* @author TobiasMahlmann
*
*/
public class MapCanvasComponent extends ChartPanel {
private static class CustomXYDotRenderer extends XYDotRenderer {
private Integer itemIndex = null;
@Override
public void drawItem( Graphics2D arg0, XYItemRendererState arg1, Rectangle2D arg2, PlotRenderingInfo arg3, XYPlot arg4, ValueAxis arg5, ValueAxis arg6,
XYDataset arg7, int arg8, int arg9, CrosshairState arg10, int arg11 ) {
if (itemIndex == null || itemIndex == arg9) {
super.drawItem( arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11 );
}
}
}
/**
*
*/
private static final long serialVersionUID = 2077175805479363567L;
private static final int DEFAULT_DOT_SIZE = 3;
private BufferedImage minimap;
private BufferedImage minimapModel;
private final String MINIMAP_FILE = "Minimap.jpg";
private final String MINIMAP_MODEL_FILE = "Mapmodel.png";
private boolean paintMapModel;
/**
* Default constructor.
*/
public MapCanvasComponent() {
super( new JFreeChart( new XYPlot( new XYSeriesCollection(), new NumberAxis( "X" ), new NumberAxis( "Y" ), new CustomXYDotRenderer() ) ) );
final Dimension size = new Dimension( 512, 512 );
setMinimumSize( size );
setMaximumSize( size );
setPreferredSize( size );
setPopupMenu( null );
final XYPlot plot = (XYPlot) getChart().getPlot();
resetDotSize();
plot.getRangeAxis().setVisible( false );
plot.getDomainAxis().setVisible( false );
getChart().getLegend().setVisible( false );
plot.setDomainGridlinesVisible( false );
plot.setRangeGridlinesVisible( false );
plot.setDomainPannable( false );
plot.setRangePannable( false );
plot.setBackgroundImageAlpha( 1f );
((NumberAxis) plot.getDomainAxis()).setRange( 64, 64 + 128 );
((NumberAxis) plot.getRangeAxis()).setRange( 64, 64 + 128 );
paintMapModel = false;
try {
URL url = MapCanvasComponent.class.getResource( MINIMAP_FILE );
minimap = ImageIO.read( url );
getChart().getPlot().setBackgroundImage( minimap );
url = MapCanvasComponent.class.getResource( MINIMAP_MODEL_FILE );
minimapModel = ImageIO.read( url );
}
catch (final IOException e) {
JOptionPane.showMessageDialog( this, e.getLocalizedMessage(), "Error loading minimap", JOptionPane.ERROR_MESSAGE );
}
}
public void addSeries( XYSeries series ) {
addSeries( series, null );
}
public void addSeries( XYSeries series, Integer index ) {
final XYSeriesCollection s = (XYSeriesCollection) ((XYPlot) getChart().getPlot()).getDataset();
s.addSeries( series );
//If we have a colour for a player. Otherwise let the component handle it
if (index != null) {
((XYPlot) getChart().getPlot()).getRenderer().setSeriesPaint( s.getSeriesIndex( series.getKey() ), Statics.PLAYER_COLOURS[index] );
}
}
/**
* @return the pencil size for painting the markers
*/
public int getDotSize() {
return ((XYDotRenderer) ((XYPlot) getChart().getPlot()).getRenderer()).getDotHeight();
}
public int getItemCount() {
final XYSeriesCollection s = (XYSeriesCollection) ((XYPlot) getChart().getPlot()).getDataset();
if (s.getSeriesCount() == 0) {
return 0;
}
else {
return s.getSeries( 0 ).getItemCount();
}
}
public XYSeriesCollection getMarkers() {
return (XYSeriesCollection) ((XYPlot) getChart().getPlot()).getDataset();
}
/**
* @return true if the zone map is currently displayed
*/
public boolean isPaintMapModel() {
return paintMapModel;
}
public void removeSeries( String series ) {
final XYSeriesCollection s = (XYSeriesCollection) ((XYPlot) getChart().getPlot()).getDataset();
final XYSeries xys = s.getSeries( series );
//If we remove a series, the series paints don't seem to get updated
final XYDotRenderer renderer = (XYDotRenderer) ((XYPlot) getChart().getPlot()).getRenderer();
final int index = s.getSeriesIndex( xys.getKey() );
for (int i = index; i < s.getSeriesCount() - 1; i++) {
renderer.setSeriesPaint( i, renderer.getSeriesPaint( i + 1 ) );
}
s.removeSeries( xys );
}
/**
* Sets the marker size to the default value
*/
public void resetDotSize() {
setDotSize( DEFAULT_DOT_SIZE );
}
public void resetTimeMarker() {
setTimeMarker( -1 );
}
/**
* Sets the pencil size for each marker. If set to a value > 1,
* the MapCanvasComponent will colour more pixels around the the actual
* marker, depending on the pencil size, to highlight the marker.
* @param dotSize
*/
public void setDotSize( int dotSize ) {
((XYDotRenderer) ((XYPlot) getChart().getPlot()).getRenderer()).setDotHeight( dotSize );
((XYDotRenderer) ((XYPlot) getChart().getPlot()).getRenderer()).setDotWidth( dotSize );
}
/**
* Set this to true if the component should render the annotated zone map
* instead of the schematic representation of the game map.
* @param paintMapModel
*/
public void setPaintMapModel( boolean paintMapModel ) {
this.paintMapModel = paintMapModel;
if (paintMapModel) {
getChart().getPlot().setBackgroundImage( minimapModel );
}
else {
getChart().getPlot().setBackgroundImage( minimap );
}
}
public void setTimeMarker( int x ) {
if (x >= 0) {
((CustomXYDotRenderer) ((XYPlot) getChart().getPlot()).getRenderer()).itemIndex = x;
}
else {
((CustomXYDotRenderer) ((XYPlot) getChart().getPlot()).getRenderer()).itemIndex = null;
}
repaint();
}
}