package nl.tudelft.bw4t.environmentstore.editor.controller;
import java.awt.Component;
import java.util.List;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import nl.tudelft.bw4t.environmentstore.editor.model.EnvironmentMap;
import nl.tudelft.bw4t.environmentstore.editor.model.ZoneModel;
import nl.tudelft.bw4t.environmentstore.editor.view.RoomMenu;
import nl.tudelft.bw4t.environmentstore.editor.view.ZoneMenu;
import nl.tudelft.bw4t.environmentstore.main.view.EnvironmentStore;
import nl.tudelft.bw4t.map.BlockColor;
import nl.tudelft.bw4t.map.NewMap;
import nl.tudelft.bw4t.map.Zone.Type;
/**
* This holds the map that the user designed. This is an abstract map containing only number of rows and columns, do not
* confuse with {@link NewMap}.
*/
public class MapPanelController implements ChangeListener {
/** basic size of the map */
private ZoneController[][] zonecontrollers;
private EnvironmentMap model;
private ColorSequenceController cscontroller;
private ZoneMenuController zmenucontroller;
private ZoneController selected = null;
private UpdateableEditorInterface uei;
public MapPanelController(EnvironmentMap map) {
cscontroller = new ColorSequenceController();
zmenucontroller = new ZoneMenuController();
this.setModel(map);
}
/**
* size of map is fixed, you can't change it after construction.
*
* @param rows amount of rows the map has.
* @param columns amount of columns the map has.
* true if labels should be shown by renderers
*/
public MapPanelController(int rows, int columns) {
this(new EnvironmentMap(rows, columns));
}
/**
* The createZone method creates a Zone and updates the UpdateableEditorInterface.
*
* @param t
* is the type of Zone that we would like to create.
* @param isDropZone
* is true if the Zone that we are creating is a dropZone.
* @param isStartZone
* is true if the Zone that we are creating is a startZone.
*/
public void createZone(Type t, boolean isDropZone, boolean isStartZone) {
if (selected != null) {
if (isDropZone && hasDropzone() && !selected.isDropZone()) {
EnvironmentStore.showDialog("Only one drop zone can be added to the map.");
} else {
if (selected.isStartZone() && hasStartzone()) {
setStartzone(isStartZone);
}
if (selected.isDropZone() && hasDropzone()) {
setDropzone(isDropZone);
}
selected.setType(t);
selected.setDropZone(isDropZone);
if (isDropZone) {
setDropzone(isDropZone);
}
selected.setStartZone(isStartZone);
if (isStartZone) {
setStartzone(isStartZone);
}
updateAll();
}
}
selected = null;
}
/**
* updates all the zones on the map
*/
private void updateAll() {
for (int i = 0; i < getRows(); i++) {
for (int j = 0; j < getColumns(); j++) {
getZoneController(i, j).getUpdateableEditorInterface().update();
}
}
}
public EnvironmentMap getModel() {
return model;
}
/**
* adds the model to the map and connects this with the neighbouring zones
* @param model the model that gets added to the map
*/
public void setModel(EnvironmentMap model) {
this.model = model;
connectZoneControllers();
}
public int getRows() {
return model.getRows();
}
public int getColumns() {
return model.getColumns();
}
public List<BlockColor> getSequence() {
return getModel().getSequence();
}
public void setSequence(List<BlockColor> colorSequence) {
getModel().setSequence(colorSequence);
}
public ZoneController[][] getZoneControllers() {
return zonecontrollers;
}
/**
* Check that given row and column are inside the actual map.
*
* @param r
* is row
* @param c
* is column
* @throws IllegalArgumentException
* if r<0, c<0, r>=rows or c>=columns
*/
public void checkCoord(int r, int c) throws IllegalArgumentException {
if (r < 0) {
throw new IllegalArgumentException("row is negative");
}
if (c < 0) {
throw new IllegalArgumentException("column is negative");
}
if (r >= zonecontrollers.length) {
throw new IllegalArgumentException("rownr is too high");
}
if (c >= zonecontrollers[0].length) {
throw new IllegalArgumentException("columnnr is too high");
}
}
public EnvironmentMap getEnvironmentMap() {
return getModel();
}
/**
* get the number of entities on the map. *
*
* @return the number of entities in the map.
*/
public int getNumberOfEntities() {
return getModel().getSpawnCount();
}
public UpdateableEditorInterface getUpdateableEditorInterface() {
return uei;
}
public void setUpdateableEditorInterface(UpdateableEditorInterface ui) {
uei = ui;
}
public ColorSequenceController getCSController() {
return cscontroller;
}
public ZoneController getSelected() {
return selected;
}
public void setSelected(ZoneController selected) {
this.selected = selected;
}
/**
* If zone is a room return menu with option to change door position
* @return return ZoneMenu
*/
public ZoneMenu getZoneMenu() {
if (selected.getType() == Type.ROOM) {
RoomMenu menu = new RoomMenu(this);
zmenucontroller.attachListenersToRoomMenu(menu, this);
return menu;
} else {
ZoneMenu menu = new ZoneMenu(this);
zmenucontroller.attachListenersToZoneMenu(menu, this);
return menu;
}
}
/**
* adds ZoneController to the grid
*/
private void connectZoneControllers() {
final ZoneController[][] original = getZoneControllers();
zonecontrollers = new ZoneController[getRows()][getColumns()];
for (int row = 0; row < getRows(); row++) {
for (int col = 0; col < getColumns(); col++) {
final ZoneModel zone = getModel().getZone(row, col);
if (original != null && row < original.length && col < original[row].length) {
final ZoneController zoneController = original[row][col];
zoneController.setZoneModel(zone);
zonecontrollers[row][col] = zoneController;
zonecontrollers[row][col].update();
} else {
zonecontrollers[row][col] = new ZoneController(this, zone);
}
}
}
final UpdateableEditorInterface uei = this.getUpdateableEditorInterface();
if (uei != null) {
uei.update();
}
}
public ZoneController getZoneController(int row, int col) {
if (getModel().isValidZone(row, col)) {
return zonecontrollers[row][col];
}
return null;
}
/**
* Show the ZoneMenu popup at given cordinates.
*
* @param component the popup
* @param x the x position of the grid
* @param y the y position of the grid
*/
public void showPopup(Component component, int x, int y) {
getZoneMenu().update();
getZoneMenu().show(component, x, y);
}
@Override
public void stateChanged(ChangeEvent e) {
this.setSequence(((ColorSequenceEditor) e.getSource()).getSequence());
}
/**
* Randomizes the BlockColors in the rooms
* @param colors the valid list of colors to randomize from
* @param amount the max amount of blocks per room
*/
public void randomizeColorsInRooms(List<BlockColor> colors, int amount) {
getModel().generateRandomBlocks(colors, amount);
for (int row = 0; row < getRows(); row++) {
for (int col = 0; col < getColumns(); col++) {
zonecontrollers[row][col].update();
}
}
}
/**
* @return the startzone
*/
public boolean hasStartzone() {
return model.hasStartzone();
}
/**
* @param startzone the startzone to set
*/
public void setStartzone(boolean startzone) {
model.setStartzone(startzone);
}
/**
* @return the dropzone
*/
public boolean hasDropzone() {
return model.hasDropzone();
}
/**
* @param dropzone the dropzone to set
*/
public void setDropzone(boolean dropzone) {
model.setDropzone(dropzone);
}
}