package mapmaker;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import mapmaker.mapcmd.*;
import util.*;
/** the Controller of mapmaker's MVC pattern
*/
public class SimpleHandler extends MapEventHandler {
public static final Object
STATE_DRAG = "STATE_DRAG",
STATE_LINK = "STATE_LINK";
AreaMap map;
NodeCollector collector;
StateController
dragState = new ConstStateController(new Boolean(true)),
linkState = dragState;
/** @param map the map to be controlled
*/
public SimpleHandler(AreaMap map) {
this.map = map;
collector = new NodeCollector();
} // Simplehandler
/** @param pos the map position of the room that was clicked upon
*/
public void roomClicked(MouseEvent e, Point pos) {
if (!e.isMetaDown()) { // left click
if (!e.isControlDown()) {
if (!e.isShiftDown())
map.execute(new CmdNewRoom(pos, MapFactory.type_DescRoom));
else {
// mark/unmark the room clicked on
Room room = map.getRoom(pos);
if (room == null)
return;
map.execute(new RCmdSetMarked(room.getPos(), !room.getMarked()));
}
}
}
else {
if (e.isControlDown()) {
// copy room description
Room source = map.getSelected();
Room target = map.getRoom(pos);
if (target != null && source != target &&
target instanceof DescObj) {
if (source == null || !(source instanceof DescObj))
((DescObj)target).setDesc(null);
else
((DescObj)target).setDesc(((DescObj)source).getDesc());
map.notifyOfChange(MapEvent.ChangeDesc);
}
return;
}
// change select state
Room room = map.getRoom(pos);
if (room == null || room == map.getSelected())
map.execute(new CmdUnselectRoom());
else
map.execute(new CmdSelectRoom(pos));
}
} // roomClicked
/** @param pressed the map position of the room where the
* mousekey was pressed down
* @param and where it was released
*/
public void roomDragged(MouseEvent e, Point pressed, Point released) {
if (!e.isMetaDown()) { // left click
if (e.isControlDown()) {
// move rooms
Room root = map.getRoom(pressed);
if (root == null)
return;
Point dir = new Point(released.x - pressed.x,
released.y - pressed.y);
Set rooms;
if (root.getMarked()) {
// move all marked rooms
Room[] roomArr = MapUtil.getMarkedRooms(map);
rooms = new HashSet();
for (int i = 0; i < roomArr.length; i++)
rooms.add(roomArr[i]);
}
else {
// move all rooms connected
rooms = collector.getNodeCollection(root, dragState.state());
}
if (MapUtil.isMoveable(map, rooms, dir))
MapUtil.moveRooms(map, rooms, dir);
return;
}
if (e.isShiftDown()) {
// mark all rooms in drag rectangel
// determin drag rectangel
int minX = Math.min(pressed.x, released.x);
int maxX = Math.max(pressed.x, released.x);
int minY = Math.min(pressed.y, released.y);
int maxY = Math.max(pressed.y, released.y);
// create and execute mapcommand to mark all rooms
CompositeCommand markCmd = new CompositeCommand();
for (int x = minX; x <= maxX; x++)
for (int y = minY; y <= maxY; y++)
markCmd.add(new RCmdSetMarked(new Point(x, y), true));
map.execute(markCmd);
return;
}
// only swap if released Point is empty
if (map.getRoom(released) == null)
map.execute(new CmdSwapRooms(pressed, released));
}
else {
// link rooms
if (((Boolean)linkState.state()).booleanValue()) {
CompositeCommand cc = new CompositeCommand();
Point[] meanRooms = MapUtil.meanRooms(map, pressed, released);
for (int i = 1; i < meanRooms.length; i++)
cc.add(new CmdLinkRooms(meanRooms[i - 1], meanRooms[i]));
map.execute(cc);
}
else
map.execute(new CmdLinkRooms(pressed, released));
}
} // roomDragged
/** @param room the Room that contains the exit that was clicked upon
* @param exit the direction of the exit that was clicked upon
*/
public void linkClicked(MouseEvent e, Point room, int exit) {
if (!e.isMetaDown()) { // left clicked
boolean blockState = map.getRoom(room).exitBlocked(exit);
map.execute(new RCmdSetExitBlocked(room, exit, !blockState));
}
} // linkClicked
/** @param room the room containing the exits that were dragged
* @param pressed the direction of the exit where the dragging started
* @param released dito
*/
public void linkDragged(MouseEvent e, Point room,
int pressed, int released) {
if (!e.isMetaDown()) // left click
map.execute(new RCmdSwapExits(room, pressed, released));
} // linkDragged
/** @param pos the map position of the room that was below the
* mouse pointer when the key was typed
*/
public void keyTypedOnRoom(KeyEvent e, Point pos) {
if (e.getKeyCode() == KeyEvent.VK_DELETE &&
!(map.getSelected() != null &&
map.getSelected().getPos().equals(pos))) {
map.execute(new CmdKillRoom(pos));
return;
}
if (e.getKeyCode() == KeyEvent.VK_V) {
map.execute(new CmdNewRoom(pos, MapFactory.type_VirtualRoom));
return;
}
} // keyTypedOnRoom
/** @param room the Room that contains the exit that was below the
* mouse pointer when the key was typed
* @param exit the direction of the exit below the mouse
*/
public void keyTypedOnLink(KeyEvent e, Point room, int exit) {
if (e.getKeyCode() == KeyEvent.VK_DELETE)
map.execute(new RCmdKillLink(room, exit));
} // keyTypedOnLink
/** adds a new StateController that the SimpleHandler can use
* to determin its state;
* @param index = STATE_DRAG: state will be used to determin
* wether up/down connections should be dragged or not
* @param index = STATE_LINK: state will be used to determin
* if mean rooms should be connected too when linking rooms
* @param state must be of type Boolean
*/
public void addStateController(StateController state,
Object index) {
if (index == STATE_DRAG)
dragState = state;
else if (index == STATE_LINK)
linkState = state;
else
throw new IllegalArgumentException("unknown state index");
} // addStateController
} // SimpleHandler