/*
* Copyright (c) 2012 Felix Mo. All rights reserved.
*
* CitySim is published under the terms of the MIT License. See the LICENSE file for more information.
*
*/
import greenfoot.*;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.Point;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.lang.Integer;
import java.util.HashMap;
/**
* Write a description of class Selection here.
*
* @author (your name)
* @version (a version number or a date)
*/
public class Selection extends Actor
{
private Tile activeTile;
private Rectangle viewport;
private boolean active = true;
private boolean selectionMode = false;
private ArrayList<Integer> acceptedTypes = new ArrayList<Integer>(); // accepted types of tiles for selection
private ArrayList<Integer> unacceptedTypes = new ArrayList<Integer>();
private ArrayList<Integer> unacceptedRoads = new ArrayList<Integer>();
private ArrayList<Integer> unacceptedZones = new ArrayList<Integer>();
private Dimension size = new Dimension(1, 1);
private boolean customSize = false;
private GreenfootImage image;
public Selection(int width, int height) {
this.image = new GreenfootImage(width, height);
setImage(this.image);
}
private void draw() {
if (activeTile == null || viewport == null || !active) return;
this.image.setTransparency(255);
this.image.clear();
if (selectionMode) {
if (!selectionIsValid()) {
this.image.setTransparency(100);
this.image.setColor(Color.RED);
this.image.fillRect((((activeTile.position().x) * Tile.SIZE) - viewport.x), (((activeTile.position().y-2) * Tile.SIZE) - viewport.y), (int)size.getWidth()*Tile.SIZE, (int)size.getHeight()*Tile.SIZE);
}
}
this.image.setColor(Color.WHITE);
this.image.drawRect((((activeTile.position().x) * Tile.SIZE) - viewport.x), (((activeTile.position().y-2) * Tile.SIZE) - viewport.y), (int)size.getWidth()*Tile.SIZE, (int)size.getHeight()*Tile.SIZE);
}
public void act() {
if (selectionMode) {
if (Greenfoot.mouseClicked(this)) {
if (selectionIsValid()) {
if (Zone.pendingOp() > 0) CSEventBus.post(new SelectionEvent(SelectionEvent.TILES_SELECTED_FOR_ZONING, selectedTiles()));
if (Road.pendingOp() > 0) CSEventBus.post(new SelectionEvent(SelectionEvent.TILE_SELECTED_FOR_ROAD, activeTile));
if (Tool.pendingOp() > 0) {
if (size.getWidth() == 1 && size.getHeight() == 1) {
CSEventBus.post(new SelectionEvent(SelectionEvent.TILE_SELECTED_FOR_TOOL, activeTile));
}
else {
CSEventBus.post(new SelectionEvent(SelectionEvent.TILES_SELECTED_FOR_TOOLS, selectedTiles()));
}
}
if (PowerGrid.pendingOp() > 0) {
if (size.getWidth() == 1 && size.getHeight() == 1) {
CSEventBus.post(new SelectionEvent(SelectionEvent.TILE_SELECTED_FOR_POWERGRID, activeTile));
}
else {
CSEventBus.post(new SelectionEvent(SelectionEvent.TILES_SELECTED_FOR_POWERGRID, selectedTiles()));
}
}
if (Recreation.pendingOp() > 0) {
if (size.getWidth() == 1 && size.getHeight() == 1) {
CSEventBus.post(new SelectionEvent(SelectionEvent.TILE_SELECTED_FOR_RECREATION, activeTile));
}
else {
CSEventBus.post(new SelectionEvent(SelectionEvent.TILES_SELECTED_FOR_RECREATION, selectedTiles()));
}
}
}
}
// Increases (up key) and decreases (down key) the selection size
String key = Greenfoot.getKey();
if (key != null) {
if (key.equalsIgnoreCase("up")) {
size.setSize(size.getWidth()+1, size.getHeight()+1);
draw();
}
else if (key.equalsIgnoreCase("down")) {
if (!(size.getWidth() == 1 && size.getHeight() == 1)) {
size.setSize(size.getWidth()-1, size.getHeight()-1);
draw();
}
}
}
if (Greenfoot.isKeyDown("escape")) {
setSelectionMode(false);
this.customSize = false;
Zone.setPendingOp(0);
Road.setPendingOp(0);
Tool.setPendingOp(0);
PowerGrid.setPendingOp(0);
Recreation.setPendingOp(0);
City.getInstance().removeHint();
}
}
else {
if (Greenfoot.mouseClicked(this)) {
if (size.width > 1) {
Query.query(Data.zoneWithTile(this.activeTile()));
}
}
}
}
public ArrayList<ArrayList<Tile>> selectedTiles() {
ArrayList<ArrayList<Tile>> tiles = Data.tiles();
ArrayList<ArrayList<Tile>> selectedTiles = new ArrayList<ArrayList<Tile>>((int)size.getWidth());
for (int i = 0; i < size.getWidth(); i++) {
selectedTiles.add(new ArrayList<Tile>((int)size.getHeight()));
}
int i = 0;
for (int x = activeTile.position().x; x < activeTile.position().x + (int)size.getWidth(); x++) {
for (int y = activeTile.position().y; y < activeTile.position().y + (int)size.getHeight(); y++) {
selectedTiles.get(i).add(tiles.get(x).get(y));
}
i++;
}
return selectedTiles;
}
private boolean selectionIsValid() {
// Check type
for (int x = activeTile.position().x; x < (activeTile.position().x + size.getWidth()); x++) {
for (int y = activeTile.position().y; y < (activeTile.position().y + size.getHeight()); y++) {
if (this.acceptedTypes.size() > 0) {
if (!acceptedTypes.contains(Data.tiles().get(x).get(y).type())) {
return false;
}
}
if (this.unacceptedTypes.size() > 0) {
if (unacceptedTypes.contains(Data.tiles().get(x).get(y).type())) {
return false;
}
}
if (this.unacceptedRoads.size() > 0) {
if (unacceptedRoads.contains(Data.tiles().get(x).get(y).road())) {
return false;
}
}
if (this.unacceptedZones.size() > 0) {
if (unacceptedZones.contains(Data.tiles().get(x).get(y).zone())) {
return false;
}
}
}
}
return true;
}
/*
* ACCESSORS *
*/
public boolean active() {
return this.active;
}
public void setActive(boolean value) {
this.active = value;
if (!this.active) {
this.image.setTransparency(0);
}
}
public boolean selectionMode() {
return this.selectionMode;
}
public void setSelectionMode(boolean value) {
CSLogger.sharedLogger().fine("Setting selection mode: " + (value ? "ON" : "OFF"));
this.size.setSize(1, 1);
this.customSize = false;
this.active = !value;
this.selectionMode = value;
if (!value) {
this.acceptedTypes.clear();
this.unacceptedTypes.clear();
this.unacceptedRoads.clear();
this.unacceptedZones.clear();
}
}
public Tile activeTile() {
return this.activeTile;
}
public void setActiveTile(Tile tile) {
try {
if (this.activeTile == tile) return;
if ((!selectionMode || Tool.pendingOp() == Bulldozer.TYPE_ID || Tool.pendingOp() == Query.TYPE_ID) && tile.zoneID() > -1) {
// ONLY SNAP IF:
// - normal mode
// - bulldozer
if (this.activeTile.zoneID() != tile.zoneID()) {
int id = Data.tilesInZoneWithID(tile.zoneID())[0];
this.activeTile = Data.tileWithID(id);
}
if (this.activeTile.zone() > 0) {
if (this.activeTile.zone() <= 3 || this.activeTile.zone() > 5) {
setSize(3, 3);
}
else if (this.activeTile.zone() > 3 && this.activeTile.zone() <= 5) {
setSize(4, 4);
}
}
this.customSize = false;
}
else {
this.activeTile = tile;
if (!this.customSize) {
setSize(1, 1);
}
}
draw();
}
catch (NullPointerException npe) {
npe.printStackTrace();
}
}
public void setViewport(Rectangle viewport) {
this.viewport = viewport;
draw();
}
public void setAcceptedTypes(int[] types) {
this.acceptedTypes.clear();
for (int type : types) {
this.acceptedTypes.add(new Integer(type));
}
}
public void setUnacceptedTypes(int[] types) {
this.unacceptedTypes.clear();
for (int type : types) {
this.unacceptedTypes.add(new Integer(type));
}
}
public void setUnacceptedRoads(int[] roads) {
this.unacceptedRoads.clear();
for (int road : roads) {
this.unacceptedRoads.add(new Integer(road));
}
}
public void setUnacceptedZones(int[] zones) {
this.unacceptedZones.clear();
for (int zone : zones) {
this.unacceptedZones.add(new Integer(zone));
}
}
public void setSize(int width, int height) {
this.size.setSize(width, height);
this.customSize = true;
}
public void setSize(Dimension size) {
this.size = size;
this.customSize = true;
}
}