/*
* Copyright (C) 2007, 2008, 2010, 2011 IsmAvatar <IsmAvatar@gmail.com>
* Copyright (C) 2007, 2008 Clam <clamisgood@gmail.com>
* Copyright (C) 2008, 2009 Quadduc <quadduc@gmail.com>
* Copyright (C) 2013, 2014 Robert B. Colton
* Copyright (C) 2014, egofree
*
* This file is part of LateralGM.
* LateralGM is free software and comes with ABSOLUTELY NO WARRANTY.
* See LICENSE for details.
*/
package org.lateralgm.subframes;
import static java.lang.Integer.MAX_VALUE;
import static javax.swing.GroupLayout.DEFAULT_SIZE;
import static javax.swing.GroupLayout.PREFERRED_SIZE;
import static org.lateralgm.main.Util.deRef;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.beans.PropertyVetoException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.GroupLayout.SequentialGroup;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.CompoundEdit;
import javax.swing.undo.UndoManager;
import javax.swing.undo.UndoableEdit;
import javax.swing.undo.UndoableEditSupport;
import org.lateralgm.components.ColorSelect;
import org.lateralgm.components.NumberField;
import org.lateralgm.components.ResourceMenu;
import org.lateralgm.components.impl.EditorScrollPane;
import org.lateralgm.components.impl.ResNode;
import org.lateralgm.components.visual.RoomEditor;
import org.lateralgm.components.visual.RoomEditor.CommandHandler;
import org.lateralgm.components.visual.RoomEditor.PRoomEditor;
import org.lateralgm.main.LGM;
import org.lateralgm.main.Prefs;
import org.lateralgm.main.UpdateSource;
import org.lateralgm.main.UpdateSource.UpdateEvent;
import org.lateralgm.main.UpdateSource.UpdateListener;
import org.lateralgm.messages.Messages;
import org.lateralgm.resources.Background;
import org.lateralgm.resources.Background.PBackground;
import org.lateralgm.resources.GmObject;
import org.lateralgm.resources.ResourceReference;
import org.lateralgm.resources.Room;
import org.lateralgm.resources.Room.PRoom;
import org.lateralgm.resources.Room.Piece;
import org.lateralgm.resources.sub.BackgroundDef;
import org.lateralgm.resources.sub.BackgroundDef.PBackgroundDef;
import org.lateralgm.resources.sub.Instance;
import org.lateralgm.resources.sub.Instance.PInstance;
import org.lateralgm.resources.sub.Tile;
import org.lateralgm.resources.sub.Tile.PTile;
import org.lateralgm.resources.sub.View;
import org.lateralgm.resources.sub.View.PView;
import org.lateralgm.subframes.CodeFrame.CodeHolder;
import org.lateralgm.ui.swing.propertylink.ButtonModelLink;
import org.lateralgm.ui.swing.propertylink.DocumentLink;
import org.lateralgm.ui.swing.propertylink.FormattedLink;
import org.lateralgm.ui.swing.propertylink.PropertyLinkFactory;
import org.lateralgm.ui.swing.util.ArrayListModel;
import org.lateralgm.util.ActiveArrayList;
import org.lateralgm.util.AddPieceInstance;
import org.lateralgm.util.ModifyPieceInstance;
import org.lateralgm.util.PropertyLink;
import org.lateralgm.util.PropertyMap.PropertyUpdateEvent;
import org.lateralgm.util.PropertyMap.PropertyUpdateListener;
import org.lateralgm.util.RemovePieceInstance;
import org.lateralgm.util.ShiftPieceInstances;
public class RoomFrame extends InstantiableResourceFrame<Room,PRoom> implements
ListSelectionListener,CommandHandler,UpdateListener,FocusListener,ChangeListener
{
private static final long serialVersionUID = 1L;
private static final ImageIcon CODE_ICON = LGM.getIconForKey("RoomFrame.CODE"); //$NON-NLS-1$
private final RoomEditor editor;
private final EditorScrollPane editorPane;
public final JTabbedPane tabs;
public JLabel statX, statY, statId, statSrc;
//ToolBar
private JButton zoomIn, zoomOut, undo, redo, deleteInstances, shiftInstances, roomControls, fill,
cut, copy, paste;
private JToggleButton gridVis, gridIso, selectObject, selectRegion, snapToGrid, addOnTop,
addMultiple;
//Objects
public JCheckBox oUnderlying, oLocked;
private ButtonModelLink<PInstance> loLocked;
public JList<Instance> oList;
private Instance lastObj = null; //non-guaranteed copy of oList.getLastSelectedValue()
private JButton addObjectButton, deleteObjectButton;
public ResourceMenu<GmObject> oNew, oSource;
private PropertyLink<PInstance,ResourceReference<GmObject>> loSource;
private JTextField objectName;
public NumberField objectHorizontalPosition, objectVerticalPosition, objectScaleX, objectScaleY,
objectRotation, objectAlpha;
public ColorSelect objectColor;
public PropertyLink<PInstance,Color> loColour;
private FormattedLink<PInstance> loX, loY, loScaleX, loScaleY, loRotation, loAlpha;
private DocumentLink<PInstance> loName;
private JButton oCreationCode;
//Settings
private JTextField sCaption;
private JCheckBox sPersistent;
private JButton sCreationCode, showButton;
private JPopupMenu showMenu;
public HashMap<CodeHolder,CodeFrame> codeFrames = new HashMap<CodeHolder,CodeFrame>();
private JCheckBoxMenuItem sSObj, sSTile, sSBack, sSFore, sSView;
//Tiles
public JComboBox<Integer> tileLayer;
// List of tiles layers in the current room
Vector<Integer> layers = new Vector<Integer>();
private JButton addLayer, deleteLayer, changeLayer;
public JCheckBox tUnderlying, tLocked, tHideOtherLayers, tEditOtherLayers;
private ButtonModelLink<PTile> ltLocked;
public TileSelector tSelect;
private JScrollPane tScroll;
public JList<Tile> tList;
private Tile lastTile = null; //non-guaranteed copy of tList.getLastSelectedValue()
private JButton deleteTileButton;
public ResourceMenu<Background> taSource, teSource;
private PropertyLink<PTile,ResourceReference<Background>> ltSource;
public NumberField tsX, tsY, tileHorizontalPosition, tileVerticalPosition, teDepth;
private FormattedLink<PTile> ltsX, ltsY, ltX, ltY, ltDepth;
//Backgrounds
private JCheckBox bDrawColor, bVisible, bForeground, bTileH, bTileV, bStretch;
private ButtonModelLink<PBackgroundDef> lbVisible, lbForeground, lbTileH, lbTileV, lbStretch;
private ColorSelect bColor;
private JList<JLabel> bList;
/**Guaranteed valid version of bList.getLastSelectedIndex()*/
private int lastValidBack = -1;
private ResourceMenu<Background> bSource;
private PropertyLink<PBackgroundDef,ResourceReference<Background>> lbSource;
private NumberField bX, bY, bH, bV;
private FormattedLink<PBackgroundDef> lbX, lbY, lbH, lbV;
private final BgDefPropertyListener bdpl = new BgDefPropertyListener();
//Views
private JCheckBox vEnabled, vVisible;
private ButtonModelLink<PView> lvVisible;
private JList<JLabel> vList;
/**Guaranteed valid version of vList.getLastSelectedIndex()*/
private int lastValidView = -1;
private NumberField vRX, vRY, vRW, vRH;
private NumberField vPX, vPY, vPW, vPH;
private FormattedLink<PView> lvRX, lvRY, lvRW, lvRH, lvPX, lvPY, lvPW, lvPH;
private ResourceMenu<GmObject> vObj;
private PropertyLink<PView,ResourceReference<GmObject>> lvObj;
private NumberField vOHBor, vOVBor, vOHSp, vOVSp;
private FormattedLink<PView> lvOHBor, lvOVBor, lvOHSp, lvOVSp;
private final ViewPropertyListener vpl = new ViewPropertyListener();
private final PropertyLinkFactory<PRoomEditor> prelf;
private JCheckBox vClear;
// Undo system elements
public UndoManager undoManager;
public UndoableEditSupport undoSupport;
// Save the object's properties for the undo
private String pieceOriginalName = null;
private Point pieceOriginalPosition = null;
private Point2D pieceOriginalScale = null;
private Double pieceOriginalRotation = null;
private Integer pieceOriginalAlpha = null;
// Used to record the select piece before losing the focus.
public Piece selectedPiece = null;
public RoomEditor getRoomEditor()
{
return editor;
}
private JToolBar makeToolBar()
{
JToolBar tool = new JToolBar();
tool.setFloatable(false);
tool.add(save);
tool.addSeparator();
// Action fired when the delete instances button is clicked
Action deleteAction = new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent actionEvent)
{
deleteAction();
}
};
// Action fired when the cut is clicked
Action cutAction = new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent actionEvent)
{
if (tabs.getSelectedIndex() == Room.TAB_TILES)
editor.copySelectionTiles();
else
editor.copySelectionInstances();
if (editor.selection != null) deleteAction(false);
}
};
cut = new JButton(LGM.getIconForKey("RoomFrame.CUT"));
cut.setToolTipText(Messages.getString("RoomFrame.CUT"));
// Bind the ctrl X keystroke with the cut button
KeyStroke ctrlXKey = KeyStroke.getKeyStroke(Messages.getKeyboardString("RoomFrame.CUT"));
cut.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(ctrlXKey,"cut");
cut.getActionMap().put("cut",cutAction);
cut.addActionListener(cutAction);
tool.add(cut);
// Action fired when the copy button is clicked
Action copyAction = new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent actionEvent)
{
if (tabs.getSelectedIndex() == Room.TAB_TILES)
editor.copySelectionTiles();
else
editor.copySelectionInstances();
}
};
copy = new JButton(LGM.getIconForKey("RoomFrame.COPY"));
copy.setToolTipText(Messages.getString("RoomFrame.COPY"));
// Bind the ctrl C keystroke with the copy button
KeyStroke ctrlCKey = KeyStroke.getKeyStroke(Messages.getKeyboardString("RoomFrame.COPY"));
copy.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(ctrlCKey,"copy");
copy.getActionMap().put("copy",copyAction);
copy.addActionListener(copyAction);
tool.add(copy);
// Action fired when the paste button is clicked
Action pasteAction = new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent actionEvent)
{
editor.activatePasteMode();
}
};
paste = new JButton(LGM.getIconForKey("RoomFrame.PASTE"));
paste.setToolTipText(Messages.getString("RoomFrame.PASTE"));
// Bind the ctrl V keystroke with the paste button
KeyStroke ctrlVKey = KeyStroke.getKeyStroke(Messages.getKeyboardString("RoomFrame.PASTE"));
paste.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(ctrlVKey,"paste");
paste.getActionMap().put("paste",pasteAction);
paste.addActionListener(pasteAction);
tool.add(paste);
tool.addSeparator();
// Action fired when the undo button is clicked
Action undoAction = new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent actionEvent)
{
Piece selectedPiece = editor.getSelectedPiece();
// If there is a selected piece, deselect it
if (selectedPiece != null) selectedPiece.setSelected(false);
undoManager.undo();
refreshUndoRedoButtons();
}
};
undo = new JButton(LGM.getIconForKey("RoomFrame.UNDO"));
undo.setToolTipText(Messages.getString("RoomFrame.UNDO"));
// Bind the undo keystroke with the undo button
KeyStroke undoKey = KeyStroke.getKeyStroke(Messages.getKeyboardString("RoomFrame.UNDO"));
undo.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(undoKey,"ctrlZ");
undo.getActionMap().put("ctrlZ",undoAction);
undo.addActionListener(undoAction);
tool.add(undo);
// Action fired when the redo button is clicked
Action redoAction = new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent actionEvent)
{
undoManager.redo();
refreshUndoRedoButtons();
}
};
redo = new JButton(LGM.getIconForKey("RoomFrame.REDO"));
redo.setToolTipText(Messages.getString("RoomFrame.REDO"));
// Bind the redo keystroke with the undo button
KeyStroke redoKey = KeyStroke.getKeyStroke(Messages.getKeyboardString("RoomFrame.REDO"));
redo.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(redoKey,"ctrlY");
redo.getActionMap().put("ctrlY",redoAction);
redo.addActionListener(redoAction);
tool.add(redo);
tool.addSeparator();
// if the select object button has been clicked, deactivate the selection region button
Action selectObjectAction = new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent actionEvent)
{
editor.deactivatePasteMode();
if (selectObject.isSelected())
editor.deactivateSelectRegionMode();
else
editor.activateSelectRegionMode();
}
};
selectObject = new JToggleButton(LGM.getIconForKey("RoomFrame.SELECT_OBJECT"));
selectObject.setToolTipText(Messages.getString("RoomFrame.SELECT_OBJECT"));
selectObject.addActionListener(selectObjectAction);
prelf.make(selectObject,PRoomEditor.SINGLE_SELECTION);
tool.add(selectObject);
// if the select region button has been clicked, deactivate the selection object button
Action selectRegionAction = new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent actionEvent)
{
editor.deactivatePasteMode();
if (selectRegion.isSelected())
editor.deactivateSelectObjectMode();
else
editor.activateSelectObjectMode();
}
};
selectRegion = new JToggleButton(LGM.getIconForKey("RoomFrame.SELECT_REGION"));
selectRegion.setToolTipText(Messages.getString("RoomFrame.SELECT_REGION"));
selectRegion.addActionListener(selectRegionAction);
prelf.make(selectRegion,PRoomEditor.MULTI_SELECTION);
tool.add(selectRegion);
fill = new JButton(LGM.getIconForKey("RoomFrame.FILL"));
fill.setToolTipText(Messages.getString("RoomFrame.FILL"));
fill.addActionListener(this);
tool.add(fill);
tool.addSeparator();
deleteInstances = new JButton(LGM.getIconForKey("RoomFrame.DELETE"));
deleteInstances.setToolTipText(Messages.getString("RoomFrame.DELETE"));
// Bind the delete keystroke with the delete button
KeyStroke deleteKey = KeyStroke.getKeyStroke(Messages.getKeyboardString("RoomFrame.DELETE"));
deleteInstances.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(deleteKey,"delete");
deleteInstances.getActionMap().put("delete",deleteAction);
deleteInstances.addActionListener(deleteAction);
tool.add(deleteInstances);
shiftInstances = new JButton(LGM.getIconForKey("RoomFrame.SHIFT"));
shiftInstances.setToolTipText(Messages.getString("RoomFrame.SHIFT"));
shiftInstances.addActionListener(this);
tool.add(shiftInstances);
tool.addSeparator();
// if the alt key has been pressed
Action altKeyPressedAction = new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent actionEvent)
{
// If bouton was clicked with the mouse
if (actionEvent.getActionCommand() != null) return;
editor.altKeyPressed();
}
};
// if the alt key has been released
Action altKeyReleasedAction = new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent actionEvent)
{
// If bouton was clicked with the mouse
if (actionEvent.getActionCommand() != null) return;
editor.altKeyReleased();
}
};
snapToGrid = new JToggleButton(LGM.getIconForKey("RoomFrame.SNAP_TO_GRID"));
snapToGrid.setToolTipText(Messages.getString("RoomFrame.SNAP_TO_GRID"));
snapToGrid.setActionCommand("snapToGrid");
// Link the alt key 'pressed'
KeyStroke altKeyPressed = KeyStroke.getKeyStroke(KeyEvent.VK_ALT,InputEvent.ALT_DOWN_MASK,false);
snapToGrid.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(altKeyPressed,"altKeyPressed");
snapToGrid.getActionMap().put("altKeyPressed",altKeyPressedAction);
snapToGrid.addActionListener(altKeyPressedAction);
// Link the alt key 'released'
KeyStroke altKeyReleased = KeyStroke.getKeyStroke(KeyEvent.VK_ALT,0,true);
snapToGrid.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(altKeyReleased,"altKeyReleased");
snapToGrid.getActionMap().put("altKeyReleased",altKeyReleasedAction);
snapToGrid.addActionListener(altKeyReleasedAction);
prelf.make(snapToGrid,PRoomEditor.SNAP_TO_GRID);
tool.add(snapToGrid);
// if the ctrl key has been pressed
Action ctrlKeyPressedAction = new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent actionEvent)
{
// If bouton was clicked with the mouse
if (actionEvent.getActionCommand() != null) return;
editor.ctrlKeyPressed();
}
};
// if the ctrl key has been released
Action ctrlKeyReleasedAction = new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent actionEvent)
{
// If bouton was clicked with the mouse
if (actionEvent.getActionCommand() != null) return;
editor.ctrlKeyReleased();
}
};
addOnTop = new JToggleButton(LGM.getIconForKey("RoomFrame.ADD_ON_TOP"));
addOnTop.setToolTipText(Messages.getString("RoomFrame.ADD_ON_TOP"));
addOnTop.setActionCommand("addOnTop");
// Link the ctrl key 'pressed'
KeyStroke ctrlKeyPressed = KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,
InputEvent.CTRL_DOWN_MASK,false);
addOnTop.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(ctrlKeyPressed,"ctrlKeyPressed");
addOnTop.getActionMap().put("ctrlKeyPressed",ctrlKeyPressedAction);
addOnTop.addActionListener(ctrlKeyPressedAction);
// Link the ctrl key 'released'
KeyStroke ctrlKeyReleased = KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL,0,true);
addOnTop.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(ctrlKeyReleased,"ctrlKeyReleased");
addOnTop.getActionMap().put("ctrlKeyReleased",ctrlKeyReleasedAction);
addOnTop.addActionListener(ctrlKeyReleasedAction);
prelf.make(addOnTop,PRoomEditor.ADD_ON_TOP);
tool.add(addOnTop);
// if the shift key has been pressed
Action shiftKeyPressedAction = new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent actionEvent)
{
// If bouton was clicked with the mouse
if (actionEvent.getActionCommand() != null) return;
editor.shiftKeyPressed();
}
};
// if the shift key has been released
Action shiftKeyReleasedAction = new AbstractAction()
{
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent actionEvent)
{
// If bouton was clicked with the mouse
if (actionEvent.getActionCommand() != null) return;
editor.shiftKeyReleased();
}
};
addMultiple = new JToggleButton(LGM.getIconForKey("RoomFrame.ADD_MULTIPLE"));
addMultiple.setToolTipText(Messages.getString("RoomFrame.ADD_MULTIPLE"));
addMultiple.setActionCommand("addMultiple");
// Link the shift key 'pressed'
KeyStroke shiftKeyPressed = KeyStroke.getKeyStroke(KeyEvent.VK_SHIFT,
InputEvent.SHIFT_DOWN_MASK,false);
addMultiple.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(shiftKeyPressed,"shiftKeyPressed");
addMultiple.getActionMap().put("shiftKeyPressed",shiftKeyPressedAction);
addMultiple.addActionListener(shiftKeyPressedAction);
// Link the shift key 'released'
KeyStroke shiftKeyReleased = KeyStroke.getKeyStroke(KeyEvent.VK_SHIFT,0,true);
addMultiple.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(shiftKeyReleased,"shiftKeyReleased");
addMultiple.getActionMap().put("shiftKeyReleased",shiftKeyReleasedAction);
addMultiple.addActionListener(shiftKeyReleasedAction);
prelf.make(addMultiple,PRoomEditor.ADD_MULTIPLE);
tool.add(addMultiple);
tool.addSeparator();
zoomIn = new JButton(LGM.getIconForKey("RoomFrame.ZOOM_IN")); //$NON-NLS-1$
zoomIn.setToolTipText(Messages.getString("RoomFrame.ZOOM_IN"));
prelf.make(zoomIn,PRoomEditor.ZOOM,1,RoomEditor.ZOOM_MAX);
tool.add(zoomIn);
zoomOut = new JButton(LGM.getIconForKey("RoomFrame.ZOOM_OUT")); //$NON-NLS-1$
zoomOut.setToolTipText(Messages.getString("RoomFrame.ZOOM_OUT"));
prelf.make(zoomOut,PRoomEditor.ZOOM,-1,RoomEditor.ZOOM_MIN);
tool.add(zoomOut);
tool.addSeparator();
gridVis = new JToggleButton(LGM.getIconForKey("RoomFrame.GRID_VISIBLE"));
gridVis.setToolTipText(Messages.getString("RoomFrame.GRID_VISIBLE"));
prelf.make(gridVis,PRoomEditor.SHOW_GRID);
tool.add(gridVis);
gridIso = new JToggleButton(LGM.getIconForKey("RoomFrame.GRID_ISOMETRIC"));
gridIso.setToolTipText(Messages.getString("RoomFrame.GRID_ISOMETRIC"));
plf.make(gridIso,PRoom.ISOMETRIC);
tool.add(gridIso);
//tool.addSeparator();
// Add the grid sizers
JLabel lab = new JLabel(Messages.getString("RoomFrame.GRID_X")); //$NON-NLS-1$
NumberField nf = new NumberField(0,999);
nf.setMaximumSize(nf.getPreferredSize());
prelf.make(nf,PRoomEditor.GRID_OFFSET_X);
tool.add(lab);
tool.add(nf);
lab = new JLabel(Messages.getString("RoomFrame.GRID_Y")); //$NON-NLS-1$
nf = new NumberField(0,999);
nf.setMaximumSize(nf.getPreferredSize());
prelf.make(nf,PRoomEditor.GRID_OFFSET_Y);
tool.add(lab);
tool.add(nf);
lab = new JLabel(Messages.getString("RoomFrame.GRID_W")); //$NON-NLS-1$
nf = new NumberField(1,999);
nf.setMaximumSize(nf.getPreferredSize());
plf.make(nf,PRoom.SNAP_X);
tool.add(lab);
tool.add(nf);
lab = new JLabel(Messages.getString("RoomFrame.GRID_H")); //$NON-NLS-1$
nf = new NumberField(1,999);
nf.setMaximumSize(nf.getPreferredSize());
plf.make(nf,PRoom.SNAP_Y);
tool.add(lab);
tool.add(nf);
tool.addSeparator();
showMenu = makeShowMenu();
showButton = new JButton(Messages.getString("RoomFrame.SHOW")); //$NON-NLS-1$
showButton.addActionListener(this);
tool.add(showButton);
tool.addSeparator();
roomControls = new JButton(LGM.getIconForKey("RoomFrame.ROOM_CONTROLS"));
roomControls.setToolTipText(Messages.getString("RoomFrame.ROOM_CONTROLS"));
roomControls.addActionListener(this);
tool.add(roomControls);
return tool;
}
private static class ObjectListComponentRenderer implements ListCellRenderer<Instance>
{
private final JLabel lab = new JLabel();
private final ListComponentRenderer lcr = new ListComponentRenderer();
public ObjectListComponentRenderer()
{
lab.setOpaque(true);
}
public Component getListCellRendererComponent(JList<? extends Instance> list, Instance val,
int ind, boolean selected, boolean focus)
{
Instance i = val;
ResourceReference<GmObject> ro = i.properties.get(PInstance.OBJECT);
GmObject o = deRef(ro);
String name = o == null ? Messages.getString("RoomFrame.NO_OBJECT") : o.getName();
lcr.getListCellRendererComponent(list,lab,ind,selected,focus);
lab.setText(name + " " + i.properties.get(PInstance.ID) + " " +
i.properties.get(PInstance.NAME));
lab.setText(String.format("%10s %6s %s", name, i.properties.get(PInstance.ID),
i.properties.get(PInstance.NAME)));
ResNode rn = o == null ? null : o.getNode();
lab.setIcon(rn == null ? null : rn.getIcon());
return lab;
}
}
private static class TileListComponentRenderer implements ListCellRenderer<Tile>
{
private final JLabel lab = new JLabel();
private final TileIcon ti = new TileIcon();
private final ListComponentRenderer lcr = new ListComponentRenderer();
public TileListComponentRenderer()
{
lab.setOpaque(true);
lab.setIcon(ti);
}
public Component getListCellRendererComponent(JList<? extends Tile> list, Tile val, int ind,
boolean selected, boolean focus)
{
Tile t = val;
ResourceReference<Background> rb = t.properties.get(PTile.BACKGROUND);
Background bg = deRef(rb);
String name = bg == null ? Messages.getString("RoomFrame.NO_BACKGROUND") : bg.getName();
lab.setText(name + " " + t.properties.get(PTile.ID) + " " + t.properties.get(PTile.NAME));
ti.tile = t;
lcr.getListCellRendererComponent(list,lab,ind,selected,focus);
return lab;
}
static class TileIcon implements Icon
{
Tile tile;
public int getIconHeight()
{
return tile.getSize().height;
}
public int getIconWidth()
{
return tile.getSize().width;
}
public void paintIcon(Component c, Graphics g, int x, int y)
{
ResourceReference<Background> rb = tile.properties.get(PTile.BACKGROUND);
Background bg = deRef(rb);
BufferedImage bi = bg == null ? null : bg.getBackgroundImage();
if (bi != null)
{
Point p = tile.getBackgroundPosition();
Dimension d = tile.getSize();
g.drawImage(bi,0,0,d.width,d.height,p.x,p.y,p.x + d.width,p.y + d.height,c);
}
}
}
}
public static final DataFlavor INSTANCE_FLAVOR = new DataFlavor(Instance.class,"Instance"); //$NON-NLS-1$
public static class ObjectListTransferable implements Transferable
{
private static final DataFlavor[] FLAVORS = { INSTANCE_FLAVOR };
private final List<Instance> instanceList;
public ObjectListTransferable(List<Instance> list)
{
instanceList = list;
}
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException
{
if (flavor == INSTANCE_FLAVOR)
{
return instanceList;
}
throw new UnsupportedFlavorException(flavor);
}
public DataFlavor[] getTransferDataFlavors()
{
return FLAVORS;
}
public boolean isDataFlavorSupported(DataFlavor flavor)
{
return flavor == INSTANCE_FLAVOR;
}
}
public class ObjectListTransferHandler extends TransferHandler
{
/**
* NOTE: Default UID generated, change if necessary.
*/
private static final long serialVersionUID = -5228856790388285912L;
private int[] indices = null;
private ArrayList<Instance> instanceList = null;
private int addIndex = -1; //Location where items were added
private int addCount = 0; //Number of items added.
public ObjectListTransferHandler(ActiveArrayList<Instance> insts)
{
instanceList = insts;
}
public boolean canImport(TransferHandler.TransferSupport info)
{
return info.isDataFlavorSupported(INSTANCE_FLAVOR);
}
protected Transferable createTransferable(JComponent c)
{
JList<Instance> list = (JList<Instance>) c;
indices = list.getSelectedIndices();
return new ObjectListTransferable(list.getSelectedValuesList());
}
/**
* We support both copy and move actions.
*/
public int getSourceActions(JComponent c)
{
return TransferHandler.COPY_OR_MOVE;
}
/**
* Perform the actual import. This demo only supports drag and drop.
*/
public boolean importData(TransferHandler.TransferSupport info)
{
if (!info.isDrop())
{
return false;
}
JList.DropLocation dl = (JList.DropLocation) info.getDropLocation();
int index = dl.getIndex();
boolean insert = dl.isInsert();
// Get the instance that is being dropped.
Transferable t = info.getTransferable();
List<Instance> data = null;
try
{
data = (List<Instance>) t.getTransferData(INSTANCE_FLAVOR);
}
catch (Exception e)
{
LGM.showDefaultExceptionHandler(e);
}
addIndex = index;
addCount = data.size();
// Perform the actual import.
for (int i = 0; i < addCount; i++)
{
instanceList.add(index++,data.get(i));
}
return true;
}
/**
* Remove the items moved from the list.
*/
protected void exportDone(JComponent c, Transferable data, int action)
{
JList<Instance> source = (JList<Instance>) c;
if (action == TransferHandler.MOVE)
{
for (int i = indices.length - 1; i >= 0; i--)
{
instanceList.remove(indices[i]);
}
}
indices = null;
addCount = 0;
addIndex = -1;
}
}
public JPanel makeObjectsPane()
{
JPanel panel = new JPanel();
GroupLayout layout = new GroupLayout(panel);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
panel.setLayout(layout);
oNew = new ResourceMenu<GmObject>(GmObject.class,
Messages.getString("RoomFrame.NO_OBJECT"),true,110); //$NON-NLS-1$
oNew.addActionListener(this);
oUnderlying = new JCheckBox(Messages.getString("RoomFrame.OBJ_UNDERLYING")); //$NON-NLS-1$
prelf.make(oUnderlying,PRoomEditor.DELETE_UNDERLYING_OBJECTS);
MouseAdapter mouseListenerForInstances = new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
// Display the selected instance with a border and centered in the editor window
showSelectedInstance();
}
};
oList = new JList<Instance>(new ArrayListModel<Instance>(res.instances));
oList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
oList.setVisibleRowCount(8);
oList.setCellRenderer(new ObjectListComponentRenderer());
oList.setSelectedIndex(0);
oList.addListSelectionListener(this);
oList.addMouseListener(mouseListenerForInstances);
//TODO: Finish
//oList.setDragEnabled(true);
//oList.setDropMode(DropMode.ON_OR_INSERT);
//oList.setTransferHandler(new ObjectListTransferHandler(res.instances));
JScrollPane sp = new JScrollPane(oList);
addObjectButton = new JButton(Messages.getString("RoomFrame.OBJ_ADD")); //$NON-NLS-1$
addObjectButton.addActionListener(this);
deleteObjectButton = new JButton(Messages.getString("RoomFrame.OBJ_DELETE")); //$NON-NLS-1$
deleteObjectButton.addActionListener(this);
JPanel edit = new JPanel();
String title = Messages.getString("RoomFrame.OBJ_INSTANCES"); //$NON-NLS-1$
edit.setBorder(BorderFactory.createTitledBorder(title));
GroupLayout layout2 = new GroupLayout(edit);
layout2.setAutoCreateGaps(true);
layout2.setAutoCreateContainerGaps(true);
edit.setLayout(layout2);
oSource = new ResourceMenu<GmObject>(GmObject.class,
Messages.getString("RoomFrame.NO_OBJECT"),true,110); //$NON-NLS-1$
oLocked = new JCheckBox(Messages.getString("RoomFrame.OBJ_LOCKED")); //$NON-NLS-1$
JLabel lObjName = new JLabel(Messages.getString("RoomFrame.OBJ_NAME")); //$NON-NLS-1$
objectName = new JTextField();
objectName.addFocusListener(this);
JLabel lObjX = new JLabel(Messages.getString("RoomFrame.OBJ_X")); //$NON-NLS-1$
objectHorizontalPosition = new NumberField(-99999,99999);
objectHorizontalPosition.setColumns(4);
objectHorizontalPosition.addFocusListener(this);
JLabel lObjY = new JLabel(Messages.getString("RoomFrame.OBJ_Y")); //$NON-NLS-1$
objectVerticalPosition = new NumberField(-99999,99999);
objectVerticalPosition.setColumns(4);
objectVerticalPosition.addFocusListener(this);
JLabel lObjScaleX = new JLabel(Messages.getString("RoomFrame.SCALE_X")); //$NON-NLS-1$
objectScaleX = new NumberField(0.1,9999.0,1.0,2);
objectScaleX.addFocusListener(this);
JLabel lObjScaleY = new JLabel(Messages.getString("RoomFrame.SCALE_Y")); //$NON-NLS-1$
objectScaleY = new NumberField(0.1,9999.0,1.0,2);
objectScaleY.addFocusListener(this);
JLabel lObjRotation = new JLabel(Messages.getString("RoomFrame.ROTATION")); //$NON-NLS-1$
objectRotation = new NumberField(0.0,360.0,0.0,2);
objectRotation.addFocusListener(this);
JLabel lObjColour = new JLabel(Messages.getString("RoomFrame.COLOUR")); //$NON-NLS-1$
objectColor = new ColorSelect(Color.WHITE,false);
objectColor.addItemListener(new ItemListener() {
Color originalColor = objectColor.getSelectedColor();
@Override
public void itemStateChanged(ItemEvent e)
{
// If no object is selected, return
int selectedIndex = oList.getSelectedIndex();
if (selectedIndex == -1) return;
// Save the selected instance
selectedPiece = oList.getSelectedValue();
if (selectedPiece == null) return;
Color newColour = objectColor.getSelectedColor();
// If the color has changed, save it in the undo
if (!originalColor.equals(newColour))
{
// Record the effect of modifying the color of an object for the undo
UndoableEdit edit = new ModifyPieceInstance(RoomFrame.this,selectedPiece,originalColor,
newColour);
// notify the listeners
undoSupport.postEdit(edit);
originalColor = objectColor.getSelectedColor();
}
}
});
JLabel lObjAlpha = new JLabel(Messages.getString("RoomFrame.ALPHA")); //$NON-NLS-1$
objectAlpha = new NumberField(0,255,255);
objectAlpha.addFocusListener(this);
oCreationCode = new JButton(Messages.getString("RoomFrame.OBJ_CODE")); //$NON-NLS-1$
oCreationCode.setIcon(CODE_ICON);
oCreationCode.addActionListener(this);
layout2.setHorizontalGroup(layout2.createParallelGroup()
/**/.addComponent(oSource)
/**/.addGroup(layout2.createSequentialGroup()
/* */.addGroup(layout2.createParallelGroup(Alignment.TRAILING)
/* */.addComponent(lObjName)
/* */.addComponent(lObjX)
/* */.addComponent(lObjScaleX)
/* */.addComponent(lObjRotation)
/* */.addComponent(lObjColour))
/* */.addGroup(layout2.createParallelGroup()
/* */.addComponent(oLocked)
/* */.addComponent(objectName)
/* */.addGroup(layout2.createSequentialGroup()
/* */.addGroup(layout2.createParallelGroup()
/* */.addComponent(objectHorizontalPosition)
/* */.addComponent(objectScaleX)
/* */.addComponent(objectRotation))
/* */.addGroup(layout2.createParallelGroup(Alignment.TRAILING)
/* */.addComponent(lObjY)
/* */.addComponent(lObjScaleY)
/* */.addComponent(lObjAlpha))
/* */.addGroup(layout2.createParallelGroup()
/* */.addComponent(objectVerticalPosition)
/* */.addComponent(objectScaleY)
/* */.addComponent(objectAlpha)))
/* */.addGroup(layout2.createSequentialGroup()
/* */.addComponent(objectColor))))
/**/.addComponent(oCreationCode,DEFAULT_SIZE,DEFAULT_SIZE,MAX_VALUE));
layout2.setVerticalGroup(layout2.createSequentialGroup()
/**/.addComponent(oSource)
/**/.addComponent(oLocked)
/**/.addGroup(layout2.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lObjName)
/* */.addComponent(objectName))
/**/.addGroup(layout2.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lObjX)
/* */.addComponent(objectHorizontalPosition)
/* */.addComponent(lObjY)
/* */.addComponent(objectVerticalPosition))
/**/.addGroup(layout2.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lObjScaleX)
/* */.addComponent(objectScaleX)
/* */.addComponent(lObjScaleY)
/* */.addComponent(objectScaleY))
/**/.addGroup(layout2.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lObjRotation)
/* */.addComponent(objectRotation)
/* */.addComponent(lObjAlpha)
/* */.addComponent(objectAlpha))
/**/.addGroup(layout2.createParallelGroup(Alignment.CENTER)
/* */.addComponent(lObjColour)
/* */.addComponent(objectColor))
/**/.addComponent(oCreationCode));
layout.setHorizontalGroup(layout.createParallelGroup()
/**/.addComponent(oNew)
/**/.addComponent(oUnderlying)
/**/.addComponent(sp,DEFAULT_SIZE,120,MAX_VALUE)
/**/.addGroup(layout.createSequentialGroup()
/* */.addComponent(addObjectButton,DEFAULT_SIZE,DEFAULT_SIZE,MAX_VALUE)
/* */.addComponent(deleteObjectButton,DEFAULT_SIZE,DEFAULT_SIZE,MAX_VALUE))
/**/.addComponent(edit));
layout.setVerticalGroup(layout.createSequentialGroup()
/**/.addComponent(oNew)
/**/.addComponent(oUnderlying)
/**/.addComponent(sp)
/**/.addGroup(layout.createParallelGroup()
/* */.addComponent(addObjectButton)
/* */.addComponent(deleteObjectButton))
/**/.addComponent(edit,PREFERRED_SIZE,PREFERRED_SIZE,PREFERRED_SIZE));
// Make sure the selected object in the list is activated
fireObjUpdate();
return panel;
}
private JPopupMenu makeShowMenu()
{
JPopupMenu showMenu = new JPopupMenu();
String st = Messages.getString("RoomFrame.SHOW_OBJECTS"); //$NON-NLS-1$
sSObj = new JCheckBoxMenuItem(st);
prelf.make(sSObj,PRoomEditor.SHOW_OBJECTS);
showMenu.add(sSObj);
st = Messages.getString("RoomFrame.SHOW_TILES"); //$NON-NLS-1$
sSTile = new JCheckBoxMenuItem(st);
prelf.make(sSTile,PRoomEditor.SHOW_TILES);
showMenu.add(sSTile);
st = Messages.getString("RoomFrame.SHOW_BACKGROUNDS"); //$NON-NLS-1$
sSBack = new JCheckBoxMenuItem(st);
prelf.make(sSBack,PRoomEditor.SHOW_BACKGROUNDS);
showMenu.add(sSBack);
st = Messages.getString("RoomFrame.SHOW_FOREGROUNDS"); //$NON-NLS-1$
sSFore = new JCheckBoxMenuItem(st);
prelf.make(sSFore,PRoomEditor.SHOW_FOREGROUNDS);
showMenu.add(sSFore);
st = Messages.getString("RoomFrame.SHOW_VIEWS"); //$NON-NLS-1$
sSView = new JCheckBoxMenuItem(st);
prelf.make(sSView,PRoomEditor.SHOW_VIEWS);
showMenu.add(sSView);
return showMenu;
}
public JPanel makeSettingsPane()
{
JPanel panel = new JPanel();
GroupLayout layout = new GroupLayout(panel);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
panel.setLayout(layout);
JLabel lName = new JLabel(Messages.getString("RoomFrame.NAME")); //$NON-NLS-1$
JLabel lCaption = new JLabel(Messages.getString("RoomFrame.CAPTION")); //$NON-NLS-1$
sCaption = new JTextField();
plf.make(sCaption.getDocument(),PRoom.CAPTION);
JLabel lWidth = new JLabel(Messages.getString("RoomFrame.WIDTH")); //$NON-NLS-1$
NumberField sWidth = new NumberField(1,999999);
plf.make(sWidth,PRoom.WIDTH);
JLabel lHeight = new JLabel(Messages.getString("RoomFrame.HEIGHT")); //$NON-NLS-1$
NumberField sHeight = new NumberField(1,999999);
plf.make(sHeight,PRoom.HEIGHT);
JLabel lSpeed = new JLabel(Messages.getString("RoomFrame.SPEED")); //$NON-NLS-1$
NumberField sSpeed = new NumberField(1,9999);
plf.make(sSpeed,PRoom.SPEED);
String str = Messages.getString("RoomFrame.PERSISTENT"); //$NON-NLS-1$
sPersistent = new JCheckBox(str);
plf.make(sPersistent,PRoom.PERSISTENT);
str = Messages.getString("RoomFrame.CREATION_CODE"); //$NON-NLS-1$
sCreationCode = new JButton(str,CODE_ICON);
sCreationCode.addActionListener(this);
JPanel pg = makeGridPane();
layout.setHorizontalGroup(layout.createParallelGroup()
/**/.addGroup(layout.createSequentialGroup()
/* */.addComponent(lName)
/* */.addComponent(name,DEFAULT_SIZE,120,MAX_VALUE))
/**/.addComponent(lCaption)
/**/.addComponent(sCaption,DEFAULT_SIZE,120,MAX_VALUE)
/**/.addGroup(layout.createSequentialGroup()
/* */.addGroup(layout.createParallelGroup(Alignment.TRAILING)
/* */.addComponent(lWidth)
/* */.addComponent(lHeight)
/* */.addComponent(lSpeed))
/* */.addGroup(layout.createParallelGroup()
/* */.addComponent(sWidth)
/* */.addComponent(sHeight)
/* */.addComponent(sSpeed)))
/**/.addComponent(sPersistent)
/**/.addComponent(sCreationCode,DEFAULT_SIZE,DEFAULT_SIZE,MAX_VALUE)
/**/.addComponent(pg));
layout.setVerticalGroup(layout.createSequentialGroup()
/**/.addGroup(layout.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lName)
/* */.addComponent(name))
/**/.addComponent(lCaption)
/**/.addComponent(sCaption,DEFAULT_SIZE,DEFAULT_SIZE,PREFERRED_SIZE)
/**/.addGroup(layout.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lWidth)
/* */.addComponent(sWidth))
/**/.addGroup(layout.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lHeight)
/* */.addComponent(sHeight))
/**/.addGroup(layout.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lSpeed)
/* */.addComponent(sSpeed))
/**/.addComponent(sPersistent)
/**/.addComponent(sCreationCode)
/**/.addComponent(pg));
return panel;
}
public JPanel makeGridPane()
{
JPanel pg = new JPanel();
GroupLayout lr = new GroupLayout(pg);
pg.setLayout(lr);
pg.setBorder(BorderFactory.createTitledBorder(Messages.getString("RoomFrame.GRID"))); //$NON-NLS-1$
JLabel lGX = new JLabel(Messages.getString("RoomFrame.GRID_X")); //$NON-NLS-1$
NumberField sGX = new NumberField(0,999);
prelf.make(sGX,PRoomEditor.GRID_OFFSET_X);
JLabel lGY = new JLabel(Messages.getString("RoomFrame.GRID_Y")); //$NON-NLS-1$
NumberField sGY = new NumberField(0,999);
prelf.make(sGY,PRoomEditor.GRID_OFFSET_Y);
JLabel lGW = new JLabel(Messages.getString("RoomFrame.GRID_W")); //$NON-NLS-1$
NumberField sGW = new NumberField(1,999);
plf.make(sGW,PRoom.SNAP_X);
JLabel lGH = new JLabel(Messages.getString("RoomFrame.GRID_H")); //$NON-NLS-1$
NumberField sGH = new NumberField(1,999);
plf.make(sGH,PRoom.SNAP_Y);
lr.setHorizontalGroup(lr.createSequentialGroup().addContainerGap()
/**/.addGroup(lr.createParallelGroup()
/* */.addComponent(lGX)
/* */.addComponent(lGY)).addGap(4)
/**/.addGroup(lr.createParallelGroup()
/* */.addComponent(sGX)
/* */.addComponent(sGY)).addGap(8)
/**/.addGroup(lr.createParallelGroup()
/* */.addComponent(lGW)
/* */.addComponent(lGH)).addGap(4)
/**/.addGroup(lr.createParallelGroup()
/* */.addComponent(sGW)
/* */.addComponent(sGH)).addContainerGap());
lr.setVerticalGroup(lr.createSequentialGroup().addGap(4)
/**/.addGroup(lr.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lGX)
/* */.addComponent(sGX)
/* */.addComponent(lGW)
/* */.addComponent(sGW)).addGap(4)
/**/.addGroup(lr.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lGY)
/* */.addComponent(sGY)
/* */.addComponent(lGH)
/* */.addComponent(sGH)).addGap(8));
return pg;
}
public JPanel makeTilesPane()
{
JPanel panel = new JPanel();
GroupLayout layout = new GroupLayout(panel);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
panel.setLayout(layout);
JLabel layer = new JLabel(Messages.getString("RoomFrame.CURRENT_TILE_LAYER"));
Room currentRoom = editor.getRoom();
// If there are already tiles in the room, get the list of layers and store it in a vector
if (!currentRoom.tiles.isEmpty())
{
layers = new Vector<Integer>();
int depth;
for (Tile tile : currentRoom.tiles)
{
depth = tile.getDepth();
if (!layers.contains(depth)) layers.add(depth);
}
}
else
{
layers.add(0);
}
// Sort the layers in descending order
Collections.sort(layers,Collections.reverseOrder());
tileLayer = new JComboBox<Integer>(layers);
tileLayer.setMaximumSize(new Dimension(Integer.MAX_VALUE,tileLayer.getHeight()));
addLayer = new JButton(Messages.getString("RoomFrame.TILE_LAYER_ADD"));
addLayer.addActionListener(this);
deleteLayer = new JButton(Messages.getString("RoomFrame.TILE_LAYER_DELETE"));
deleteLayer.addActionListener(this);
changeLayer = new JButton(Messages.getString("RoomFrame.TILE_LAYER_CHANGE"));
changeLayer.addActionListener(this);
tHideOtherLayers = new JCheckBox(Messages.getString("RoomFrame.TILE_HIDE_OTHER_LAYERS"));
tHideOtherLayers.addActionListener(this);
tEditOtherLayers = new JCheckBox(Messages.getString("RoomFrame.TILE_EDIT_OTHER_LAYERS"));
tEditOtherLayers.addActionListener(this);
JTabbedPane tab = new JTabbedPane();
tab.addTab(Messages.getString("RoomFrame.TILE_ADD"),makeTilesAddPane());
tab.addTab(Messages.getString("RoomFrame.TILE_EDIT"),makeTilesEditPane());
tab.setSelectedIndex(0);
layout.setHorizontalGroup(layout.createParallelGroup()
/**/.addGroup(layout.createSequentialGroup()
/* */.addComponent(layer)
/* */.addComponent(tileLayer))
/**/.addGroup(layout.createSequentialGroup()
/* */.addComponent(addLayer,DEFAULT_SIZE,PREFERRED_SIZE,MAX_VALUE)
/* */.addComponent(deleteLayer,DEFAULT_SIZE,PREFERRED_SIZE,MAX_VALUE)
/* */.addComponent(changeLayer,DEFAULT_SIZE,PREFERRED_SIZE,MAX_VALUE))
/**/.addGroup(
layout.createSequentialGroup()
/* */.addComponent(tHideOtherLayers,GroupLayout.PREFERRED_SIZE,GroupLayout.DEFAULT_SIZE,
GroupLayout.PREFERRED_SIZE)
/* */.addComponent(tEditOtherLayers))
/**/.addComponent(tab));
layout.setVerticalGroup(layout.createSequentialGroup()
/**/.addGroup(layout.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(layer)
/* */.addComponent(tileLayer))
/**/.addGroup(layout.createParallelGroup()
/* */.addComponent(addLayer)
/* */.addComponent(deleteLayer)
/* */.addComponent(changeLayer))
/**/.addGroup(layout.createParallelGroup()
/* */.addComponent(tHideOtherLayers)
/* */.addComponent(tEditOtherLayers))
/**/.addComponent(tab));
fireTileUpdate();
return panel;
}
public JPanel makeTilesAddPane()
{
JPanel panel = new JPanel();
GroupLayout layout = new GroupLayout(panel);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
panel.setLayout(layout);
taSource = new ResourceMenu<Background>(Background.class,
Messages.getString("RoomFrame.NO_BACKGROUND"),true,110);
taSource.addActionListener(this);
tSelect = new TileSelector();
tScroll = new JScrollPane(tSelect);
tScroll.setPreferredSize(tScroll.getSize());
tUnderlying = new JCheckBox(Messages.getString("RoomFrame.TILE_UNDERLYING")); //$NON-NLS-1$
prelf.make(tUnderlying,PRoomEditor.DELETE_UNDERLYING_TILES);
layout.setHorizontalGroup(layout.createParallelGroup()
/**/.addComponent(tScroll)
/**/.addComponent(taSource)
/**/.addComponent(tUnderlying));
layout.setVerticalGroup(layout.createSequentialGroup()
/**/.addComponent(tScroll)
/**/.addComponent(taSource)
/**/.addComponent(tUnderlying));
return panel;
}
//XXX: Extract to own class?
public static class TileSelector extends JLabel
{
private static final long serialVersionUID = 1L;
public int tx, ty;
private ResourceReference<Background> bkg;
public TileSelector()
{
super();
setVerticalAlignment(TOP);
enableEvents(MouseEvent.MOUSE_PRESSED);
enableEvents(MouseEvent.MOUSE_DRAGGED);
}
public void setBackground(ResourceReference<Background> bkg)
{
this.bkg = bkg;
Background b = deRef(bkg);
if (b == null)
{
setIcon(null);
setPreferredSize(new Dimension(0,0));
return;
}
setPreferredSize(new Dimension(b.getWidth(),b.getHeight()));
BufferedImage bi = b.getDisplayImage();
setIcon(bi == null ? null : new ImageIcon(bi));
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Background b = deRef(bkg);
if (b == null) return;
//BufferedImage img = bkg.getDisplayImage();
//if (img == null) return;
Shape oldClip = g.getClip(); //backup the old clip
Rectangle oldc = g.getClipBounds();
//Set the clip properly
g.setClip(new Rectangle(oldc.x,oldc.y,Math.min(oldc.x + oldc.width,b.getWidth()) - oldc.x,
Math.min(oldc.y + oldc.height,b.getHeight()) - oldc.y));
if ((Boolean) b.get(PBackground.USE_AS_TILESET))
{
g.setXORMode(Color.BLACK);
g.setColor(Color.WHITE);
g.drawRect(tx,ty,(Integer) b.get(PBackground.TILE_WIDTH),
(Integer) b.get(PBackground.TILE_HEIGHT));
g.setPaintMode(); //just in case
}
g.setClip(oldClip); //restore the clip
}
@Override
protected void processMouseEvent(MouseEvent e)
{
if (e.getID() == MouseEvent.MOUSE_PRESSED && e.getButton() == MouseEvent.BUTTON1
&& e.getX() < getPreferredSize().width && e.getY() < getPreferredSize().height)
selectTile(e.getX(),e.getY());
super.processMouseEvent(e);
}
@Override
protected void processMouseMotionEvent(MouseEvent e)
{
if (e.getID() == MouseEvent.MOUSE_DRAGGED
&& (e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) != 0)
selectTile(e.getX(),e.getY());
super.processMouseMotionEvent(e);
}
public void selectTile(int x, int y)
{
Background hardBkg = deRef(bkg);
if (hardBkg == null)
{
tx = x;
ty = y;
}
else if (!(Boolean) hardBkg.get(PBackground.USE_AS_TILESET))
{
tx = 0;
ty = 0;
}
else
{
int w = (Integer) hardBkg.get(PBackground.TILE_WIDTH)
+ (Integer) hardBkg.get(PBackground.H_SEP);
int h = (Integer) hardBkg.get(PBackground.TILE_HEIGHT)
+ (Integer) hardBkg.get(PBackground.V_SEP);
int ho = hardBkg.get(PBackground.H_OFFSET);
int vo = hardBkg.get(PBackground.V_OFFSET);
tx = (int) Math.floor((x - ho) / w) * w + ho;
ty = (int) Math.floor((y - vo) / h) * h + vo;
}
repaint();
}
}
public JPanel makeTilesEditPane()
{
JPanel panel = new JPanel();
GroupLayout layout = new GroupLayout(panel);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
panel.setLayout(layout);
MouseAdapter mouseListenerForTiles = new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
// Display the selected tile with a border and centered in the editor window
showSelectedTile();
}
};
tList = new JList<Tile>(new ArrayListModel<Tile>(res.tiles));
tList.addListSelectionListener(this);
tList.addMouseListener(mouseListenerForTiles);
tList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
tList.setCellRenderer(new TileListComponentRenderer());
JScrollPane sp = new JScrollPane(tList);
deleteTileButton = new JButton(Messages.getString("RoomFrame.TILE_DELETE")); //$NON-NLS-1$
deleteTileButton.addActionListener(this);
tLocked = new JCheckBox(Messages.getString("RoomFrame.TILE_LOCKED")); //$NON-NLS-1$
JPanel pSet = new JPanel();
pSet.setBorder(BorderFactory.createTitledBorder(Messages.getString("RoomFrame.TILESET"))); //$NON-NLS-1$
GroupLayout psl = new GroupLayout(pSet);
psl.setAutoCreateGaps(true);
psl.setAutoCreateContainerGaps(true);
pSet.setLayout(psl);
teSource = new ResourceMenu<Background>(Background.class,
Messages.getString("RoomFrame.NO_BACKGROUND"),true,110); //$NON-NLS-1$
JLabel ltsx = new JLabel(Messages.getString("RoomFrame.TILESET_X")); //$NON-NLS-1$
tsX = new NumberField(0);
tsX.setColumns(4);
JLabel ltsy = new JLabel(Messages.getString("RoomFrame.TILESET_Y")); //$NON-NLS-1$
tsY = new NumberField(0);
tsY.setColumns(4);
psl.setHorizontalGroup(psl.createParallelGroup()
/**/.addComponent(teSource)
/**/.addGroup(psl.createSequentialGroup()
/* */.addComponent(ltsx)
/* */.addComponent(tsX)
/* */.addComponent(ltsy)
/* */.addComponent(tsY)));
psl.setVerticalGroup(psl.createSequentialGroup()
/**/.addComponent(teSource)
/**/.addGroup(psl.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(ltsx)
/* */.addComponent(tsX)
/* */.addComponent(ltsy)
/* */.addComponent(tsY)));
JPanel pTile = new JPanel();
pTile.setBorder(BorderFactory.createTitledBorder(Messages.getString("RoomFrame.TILE"))); //$NON-NLS-1$
GroupLayout ptl = new GroupLayout(pTile);
ptl.setAutoCreateGaps(true);
ptl.setAutoCreateContainerGaps(true);
pTile.setLayout(ptl);
JLabel ltx = new JLabel(Messages.getString("RoomFrame.TILE_X")); //$NON-NLS-1$
tileHorizontalPosition = new NumberField(0);
tileHorizontalPosition.setColumns(4);
tileHorizontalPosition.addFocusListener(this);
JLabel lty = new JLabel(Messages.getString("RoomFrame.TILE_Y")); //$NON-NLS-1$
tileVerticalPosition = new NumberField(0);
tileVerticalPosition.setColumns(4);
tileVerticalPosition.addFocusListener(this);
JLabel ltl = new JLabel(Messages.getString("RoomFrame.TILE_LAYER")); //$NON-NLS-1$
teDepth = new NumberField(0);
teDepth.setColumns(8);
ptl.setHorizontalGroup(ptl.createParallelGroup()
/**/.addGroup(ptl.createSequentialGroup()
/* */.addComponent(ltx)
/* */.addComponent(tileHorizontalPosition)
/* */.addComponent(lty)
/* */.addComponent(tileVerticalPosition))
/**/.addGroup(ptl.createSequentialGroup()
/* */.addComponent(ltl)
/* */.addComponent(teDepth)));
ptl.setVerticalGroup(ptl.createSequentialGroup()
/**/.addGroup(ptl.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(ltx)
/* */.addComponent(tileHorizontalPosition)
/* */.addComponent(lty)
/* */.addComponent(tileVerticalPosition))
/**/.addGroup(ptl.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(ltl)
/* */.addComponent(teDepth)));
layout.setHorizontalGroup(layout.createParallelGroup()
/**/.addComponent(sp,DEFAULT_SIZE,120,MAX_VALUE)
/**/.addComponent(deleteTileButton,DEFAULT_SIZE,DEFAULT_SIZE,MAX_VALUE)
/**/.addComponent(tLocked)
/**/.addComponent(pSet)
/**/.addComponent(pTile));
layout.setVerticalGroup(layout.createSequentialGroup()
/**/.addComponent(sp,DEFAULT_SIZE,60,MAX_VALUE)
/**/.addComponent(deleteTileButton)
/**/.addComponent(tLocked)
/**/.addComponent(pSet)
/**/.addComponent(pTile));
return panel;
}
//TODO 1.7?: Batch tile operations
public static JPanel makeTilesBatchPane()
{
JPanel panel = new JPanel();
// GroupLayout layout = new GroupLayout(panel);
// layout.setAutoCreateGaps(true);
// layout.setAutoCreateContainerGaps(true);
// panel.setLayout(layout);
//TODO: Translate
panel.add(new JLabel("<html>This tab will offer ways to<br />"
+ "perform batch operations on several<br />"
+ "tiles at once, or regions of tiles.</html>"));
return panel;
}
public JPanel makeBackgroundsPane()
{
JPanel panel = new JPanel();
GroupLayout layout = new GroupLayout(panel);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
panel.setLayout(layout);
bDrawColor = new JCheckBox(Messages.getString("RoomFrame.DRAW_COLOR")); //$NON-NLS-1$
plf.make(bDrawColor,PRoom.DRAW_BACKGROUND_COLOR);
JLabel lColor = new JLabel(Messages.getString("RoomFrame.COLOR")); //$NON-NLS-1$
bColor = new ColorSelect();
plf.make(bColor,PRoom.BACKGROUND_COLOR);
JLabel[] backLabs = new JLabel[res.backgroundDefs.size()];
for (int i = 0; i < backLabs.length; i++)
{
backLabs[i] = new JLabel(" " + Messages.getString("RoomFrame.BACK") + i); //$NON-NLS-1$
boolean v = res.backgroundDefs.get(i).properties.get(PBackgroundDef.VISIBLE);
backLabs[i].setFont(backLabs[i].getFont().deriveFont(v ? Font.BOLD : Font.PLAIN));
backLabs[i].setOpaque(true);
}
bList = new JList<JLabel>(backLabs);
bList.setCellRenderer(new ListComponentRenderer());
bList.addListSelectionListener(this);
bList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
bList.setVisibleRowCount(4);
JScrollPane sp = new JScrollPane(bList);
for (BackgroundDef d : res.backgroundDefs)
d.properties.getUpdateSource(PBackgroundDef.VISIBLE).addListener(bdpl);
bVisible = new JCheckBox(Messages.getString("RoomFrame.BACK_VISIBLE")); //$NON-NLS-1$
bForeground = new JCheckBox(Messages.getString("RoomFrame.BACK_FOREGROUND")); //$NON-NLS-1$
bSource = new ResourceMenu<Background>(Background.class,
Messages.getString("RoomFrame.NO_BACKGROUND"),true,150); //$NON-NLS-1$
bTileH = new JCheckBox(Messages.getString("RoomFrame.BACK_TILE_HOR")); //$NON-NLS-1$
JLabel lbx = new JLabel(Messages.getString("RoomFrame.BACK_X")); //$NON-NLS-1$
bX = new NumberField(0);
bX.setColumns(4);
bTileV = new JCheckBox(Messages.getString("RoomFrame.BACK_TILE_VERT")); //$NON-NLS-1$
JLabel lby = new JLabel(Messages.getString("RoomFrame.BACK_Y")); //$NON-NLS-1$
bY = new NumberField(0);
bY.setColumns(4);
bStretch = new JCheckBox(Messages.getString("RoomFrame.BACK_STRETCH")); //$NON-NLS-1$
JLabel lbh = new JLabel(Messages.getString("RoomFrame.BACK_HSPEED")); //$NON-NLS-1$
bH = new NumberField(-999,999);
JLabel lbv = new JLabel(Messages.getString("RoomFrame.BACK_VSPEED")); //$NON-NLS-1$
bV = new NumberField(-999,999);
bList.setSelectedIndex(0);
Insets spi = sp.getInsets();
int spmh = bList.getMaximumSize().height + spi.bottom + spi.top;
layout.setHorizontalGroup(layout.createParallelGroup()
/**/.addComponent(bDrawColor)
/**/.addGroup(layout.createSequentialGroup()
/* */.addComponent(lColor)
/* */.addComponent(bColor))
/**/.addComponent(sp)
/**/.addGroup(layout.createSequentialGroup()
/* */.addComponent(bVisible)
/* */.addComponent(bForeground))
/**/.addComponent(bSource)
/**/.addGroup(layout.createSequentialGroup()
/* */.addComponent(lbx)
/* */.addComponent(bX)
/* */.addComponent(lby)
/* */.addComponent(bY))
/**/.addGroup(layout.createSequentialGroup()
/* */.addGroup(layout.createParallelGroup(Alignment.TRAILING)
/* */.addComponent(lbh)
/* */.addComponent(lbv))
/* */.addGroup(layout.createParallelGroup()
/* */.addComponent(bH)
/* */.addComponent(bV)))
/**/.addComponent(bTileH)
/**/.addComponent(bTileV)
/**/.addComponent(bStretch));
layout.setVerticalGroup(layout.createSequentialGroup()
/**/.addComponent(bDrawColor)
/**/.addGroup(layout.createParallelGroup(Alignment.BASELINE,false)
/* */.addComponent(lColor)
/* */.addComponent(bColor))
/**/.addComponent(sp,DEFAULT_SIZE,DEFAULT_SIZE,spmh)
/**/.addGroup(layout.createParallelGroup()
/* */.addComponent(bVisible)
/* */.addComponent(bForeground))
/**/.addComponent(bSource)
/**/.addGroup(layout.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lbx)
/* */.addComponent(bX)
/* */.addComponent(lby)
/* */.addComponent(bY))
/**/.addGroup(layout.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lbh)
/* */.addComponent(bH))
/**/.addGroup(layout.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lbv)
/* */.addComponent(bV))
/**/.addComponent(bTileH)
/**/.addComponent(bTileV)
/**/.addComponent(bStretch));
return panel;
}
public JPanel makePhysicsPane()
{
JPanel panel = new JPanel();
JCheckBox phyWorldCB = new JCheckBox(Messages.getString("RoomFrame.PHY_WORLD_ENABLED"));
plf.make(phyWorldCB,PRoom.PHYSICS_WORLD);
JLabel pixMetersLabel = new JLabel(Messages.getString("RoomFrame.PHY_PIXELSPERMETER"));
NumberField pixMetersField = new NumberField(0.1000);
plf.make(pixMetersField,PRoom.PHYSICS_PIXTOMETERS);
pixMetersField.setColumns(16);
JLabel gravityXLabel = new JLabel(Messages.getString("RoomFrame.PHY_GRAVITY_X"));
NumberField gravityXField = new NumberField(0.0);
plf.make(gravityXField,PRoom.PHYSICS_GRAVITY_X);
gravityXField.setColumns(16);
JLabel gravityYLabel = new JLabel(Messages.getString("RoomFrame.PHY_GRAVITY_Y"));
NumberField gravityYField = new NumberField(10.0);
plf.make(gravityYField,PRoom.PHYSICS_GRAVITY_Y);
gravityYField.setColumns(16);
GroupLayout layout = new GroupLayout(panel);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
panel.setLayout(layout);
layout.setHorizontalGroup(layout.createParallelGroup()
/**/.addComponent(phyWorldCB)
/**/.addGroup(layout.createSequentialGroup()
/* */.addComponent(pixMetersLabel)
/* */.addComponent(pixMetersField))
/**/.addGroup(layout.createSequentialGroup()
/* */.addComponent(gravityXLabel)
/* */.addComponent(gravityXField))
/**/.addGroup(layout.createSequentialGroup()
/* */.addComponent(gravityYLabel)
/* */.addComponent(gravityYField)));
layout.setVerticalGroup(layout.createSequentialGroup()
/**/.addComponent(phyWorldCB)
/**/.addGroup(layout.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(pixMetersLabel)
/* */.addComponent(pixMetersField))
/**/.addGroup(layout.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(gravityXLabel)
/* */.addComponent(gravityXField))
/**/.addGroup(layout.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(gravityYLabel)
/* */.addComponent(gravityYField)));
return panel;
}
public JPanel makeViewsPane()
{
JPanel panel = new JPanel();
GroupLayout layout = new GroupLayout(panel);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
panel.setLayout(layout);
vEnabled = new JCheckBox(Messages.getString("RoomFrame.VIEWS_ENABLED")); //$NON-NLS-1$
plf.make(vEnabled,PRoom.VIEWS_ENABLED);
vClear = new JCheckBox(Messages.getString("RoomFrame.VIEWS_CLEAR")); //$NON-NLS-1$
plf.make(vClear,PRoom.VIEWS_CLEAR);
JLabel[] viewLabs = new JLabel[res.views.size()];
for (int i = 0; i < viewLabs.length; i++)
{
viewLabs[i] = new JLabel(" " + Messages.getString("RoomFrame.VIEW") + i); //$NON-NLS-1$
boolean v = res.views.get(i).properties.get(PView.VISIBLE);
viewLabs[i].setFont(viewLabs[i].getFont().deriveFont(v ? Font.BOLD : Font.PLAIN));
viewLabs[i].setOpaque(true);
}
vList = new JList<JLabel>(viewLabs);
vList.setCellRenderer(new ListComponentRenderer());
//vList.setVisibleRowCount(4);
vList.addListSelectionListener(this);
vList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JScrollPane sp = new JScrollPane(vList);
for (View v : res.views)
{
v.properties.getUpdateSource(PView.VISIBLE).addListener(vpl);
v.properties.getUpdateSource(PView.OBJECT).addListener(vpl);
v.properties.getUpdateSource(PView.VIEW_W).addListener(vpl);
v.properties.getUpdateSource(PView.VIEW_H).addListener(vpl);
v.properties.getUpdateSource(PView.BORDER_H).addListener(vpl);
v.properties.getUpdateSource(PView.BORDER_V).addListener(vpl);
}
vVisible = new JCheckBox(Messages.getString("RoomFrame.VIEW_ENABLED")); //$NON-NLS-1$
JTabbedPane tp = makeViewsDimensionsPane();
JPanel pf = makeViewsFollowPane();
vList.setSelectedIndex(0);
Insets spi = sp.getInsets();
int spmh = vList.getMaximumSize().height + spi.bottom + spi.top;
layout.setHorizontalGroup(layout.createParallelGroup()
/**/.addComponent(vEnabled)
/**/.addComponent(vClear)
/**/.addComponent(sp)
/**/.addComponent(vVisible)
/**/.addComponent(tp)
/**/.addComponent(pf));
layout.setVerticalGroup(layout.createSequentialGroup()
/**/.addComponent(vEnabled)
/**/.addComponent(vClear)
/**/.addComponent(sp,DEFAULT_SIZE,DEFAULT_SIZE,spmh)
/**/.addComponent(vVisible)
/**/.addComponent(tp,DEFAULT_SIZE,DEFAULT_SIZE,PREFERRED_SIZE)
/**/.addComponent(pf));
return panel;
}
private JTabbedPane makeViewsDimensionsPane()
{
JPanel pr = new JPanel();
GroupLayout lr = new GroupLayout(pr);
pr.setLayout(lr);
JLabel lRX = new JLabel(Messages.getString("RoomFrame.VIEW_X")); //$NON-NLS-1$
vRX = new NumberField(0,999999);
JLabel lRW = new JLabel(Messages.getString("RoomFrame.VIEW_W")); //$NON-NLS-1$
vRW = new NumberField(1,999999);
JLabel lRY = new JLabel(Messages.getString("RoomFrame.VIEW_Y")); //$NON-NLS-1$
vRY = new NumberField(0,999999);
JLabel lRH = new JLabel(Messages.getString("RoomFrame.VIEW_H")); //$NON-NLS-1$
vRH = new NumberField(1,999999);
lr.setHorizontalGroup(lr.createSequentialGroup().addContainerGap()
/**/.addGroup(lr.createParallelGroup()
/* */.addComponent(lRX)
/* */.addComponent(lRY)).addGap(4)
/**/.addGroup(lr.createParallelGroup()
/* */.addComponent(vRX)
/* */.addComponent(vRY)).addGap(8)
/**/.addGroup(lr.createParallelGroup()
/* */.addComponent(lRW)
/* */.addComponent(lRH)).addGap(4)
/**/.addGroup(lr.createParallelGroup()
/* */.addComponent(vRW)
/* */.addComponent(vRH)).addContainerGap());
lr.setVerticalGroup(lr.createSequentialGroup().addGap(4)
/**/.addGroup(lr.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lRX)
/* */.addComponent(vRX)
/* */.addComponent(lRW)
/* */.addComponent(vRW)).addGap(4)
/**/.addGroup(lr.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lRY)
/* */.addComponent(vRY)
/* */.addComponent(lRH)
/* */.addComponent(vRH)).addGap(8));
JPanel pp = new JPanel();
GroupLayout lp = new GroupLayout(pp);
pp.setLayout(lp);
JLabel lPX = new JLabel(Messages.getString("RoomFrame.PORT_X")); //$NON-NLS-1$
vPX = new NumberField(0,999999);
JLabel lPW = new JLabel(Messages.getString("RoomFrame.PORT_W")); //$NON-NLS-1$
vPW = new NumberField(1,999999);
JLabel lPY = new JLabel(Messages.getString("RoomFrame.PORT_Y")); //$NON-NLS-1$
vPY = new NumberField(0,999999);
JLabel lPH = new JLabel(Messages.getString("RoomFrame.PORT_H")); //$NON-NLS-1$
vPH = new NumberField(1,999999);
lp.setHorizontalGroup(lp.createSequentialGroup().addContainerGap()
/**/.addGroup(lp.createParallelGroup()
/* */.addComponent(lPX)
/* */.addComponent(lPY)).addGap(4)
/**/.addGroup(lp.createParallelGroup()
/* */.addComponent(vPX)
/* */.addComponent(vPY)).addGap(8)
/**/.addGroup(lp.createParallelGroup()
/* */.addComponent(lPW)
/* */.addComponent(lPH)).addGap(4)
/**/.addGroup(lp.createParallelGroup()
/* */.addComponent(vPW)
/* */.addComponent(vPH)).addContainerGap());
lp.setVerticalGroup(lp.createSequentialGroup().addGap(4)
/**/.addGroup(lp.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lPX)
/* */.addComponent(vPX)
/* */.addComponent(lPW)
/* */.addComponent(vPW)).addGap(4)
/**/.addGroup(lp.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lPY)
/* */.addComponent(vPY)
/* */.addComponent(lPH)
/* */.addComponent(vPH)).addGap(8));
JTabbedPane tp = new JTabbedPane();
tp.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
tp.addTab(Messages.getString("RoomFrame.VIEW_IN_ROOM"),pr); //$NON-NLS-1$
tp.addTab(Messages.getString("RoomFrame.PORT"),pp); //$NON-NLS-1$
return tp;
}
private JPanel makeViewsFollowPane()
{
JPanel pf = new JPanel();
pf.setBorder(BorderFactory.createTitledBorder(Messages.getString("RoomFrame.FOLLOW"))); //$NON-NLS-1$
GroupLayout lf = new GroupLayout(pf);
pf.setLayout(lf);
vObj = new ResourceMenu<GmObject>(GmObject.class,
Messages.getString("RoomFrame.NO_OBJECT"),true,110); //$NON-NLS-1$
JLabel lH = new JLabel(Messages.getString("RoomFrame.VIEW_HORIZONTAL"));
JLabel lV = new JLabel(Messages.getString("RoomFrame.VIEW_VERTICAL"));
JLabel lBorder = new JLabel(Messages.getString("RoomFrame.VIEW_BORDER"));
JLabel lSpeed = new JLabel(Messages.getString("RoomFrame.VIEW_SPEED"));
vOHBor = new NumberField(0,32000);
vOHSp = new NumberField(-1,32000);
vOVBor = new NumberField(0,32000);
vOVSp = new NumberField(-1,32000);
lf.setHorizontalGroup(lf.createSequentialGroup().addContainerGap()
/**/.addGroup(lf.createParallelGroup()
/* */.addComponent(vObj)
/* */.addGroup(lf.createSequentialGroup()
/* */.addGroup(lf.createParallelGroup(Alignment.TRAILING)
/* */.addComponent(lH)
/* */.addComponent(lV)).addGap(4)
/* */.addGroup(lf.createParallelGroup()
/* */.addComponent(lBorder)
/* */.addComponent(vOHBor)
/* */.addComponent(vOVBor)).addGap(4)
/* */.addGroup(lf.createParallelGroup()
/* */.addComponent(lSpeed)
/* */.addComponent(vOHSp)
/* */.addComponent(vOVSp)))).addContainerGap());
lf.setVerticalGroup(lf.createSequentialGroup().addGap(4)
/**/.addComponent(vObj).addGap(4)
/* */.addGroup(lf.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lBorder)
/* */.addComponent(lSpeed)).addGap(4)
/* */.addGroup(lf.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lH)
/* */.addComponent(vOHBor)
/* */.addComponent(vOHSp)).addGap(4)
/* */.addGroup(lf.createParallelGroup(Alignment.BASELINE)
/* */.addComponent(lV)
/* */.addComponent(vOVBor)
/* */.addComponent(vOVSp)).addGap(8));
return pf;
}
private JPanel makeStatsPane()
{
JPanel stat = new JPanel();
stat.setLayout(new BoxLayout(stat,BoxLayout.X_AXIS));
stat.setMaximumSize(new Dimension(Integer.MAX_VALUE,11));
statX = new JLabel(Messages.getString("RoomFrame.STAT_X")); //$NON-NLS-1$
statX.setMaximumSize(new Dimension(50,14));
stat.add(statX);
//stat.add(new JLabel("|")); //$NON-NLS-1$
//visible divider ^ since JSeparator isn't visible
JSeparator sep;
sep = new JSeparator(JSeparator.VERTICAL);
sep.setMaximumSize(new Dimension(8,sep.getMaximumSize().height));
stat.add(sep);
statY = new JLabel(Messages.getString("RoomFrame.STAT_Y")); //$NON-NLS-1$
statY.setMaximumSize(new Dimension(50,13));
stat.add(statY);
sep = new JSeparator(JSeparator.VERTICAL);
sep.setMaximumSize(new Dimension(8,sep.getMaximumSize().height));
stat.add(sep);
statId = new JLabel();
stat.add(statId);
sep = new JSeparator(JSeparator.VERTICAL);
sep.setMaximumSize(new Dimension(8,sep.getMaximumSize().height));
stat.add(sep);
statSrc = new JLabel();
stat.add(statSrc); //resizes at will, so no Max size
return stat;
}
public RoomFrame(Room res, ResNode node)
{
super(res,node);
editor = new RoomEditor(res,this);
prelf = new PropertyLinkFactory<PRoomEditor>(editor.properties,null);
GroupLayout layout = new GroupLayout(getContentPane())
{
@Override
public void layoutContainer(Container parent)
{
Dimension m = RoomFrame.this.getMinimumSize();
Dimension s = RoomFrame.this.getSize();
Dimension r = new Dimension(Math.max(m.width,s.width),Math.max(m.height,s.height));
if (!r.equals(s))
RoomFrame.this.setSize(r);
else
super.layoutContainer(parent);
}
};
setLayout(layout);
JToolBar tools = makeToolBar();
//conveniently, these tabs happen to have the same indexes as GM's tabs
tabs = new JTabbedPane();
tabs.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT);
tabs.addTab(Messages.getString("RoomFrame.TAB_OBJECTS"),makeObjectsPane()); //$NON-NLS-1$
tabs.addTab(Messages.getString("RoomFrame.TAB_SETTINGS"),makeSettingsPane()); //$NON-NLS-1$
tabs.addTab(Messages.getString("RoomFrame.TAB_TILES"),makeTilesPane()); //$NON-NLS-1$
String bks = Messages.getString("RoomFrame.TAB_BACKGROUNDS"); //$NON-NLS-1$
tabs.addTab(bks,makeBackgroundsPane());
tabs.addTab(Messages.getString("RoomFrame.TAB_VIEWS"),makeViewsPane()); //$NON-NLS-1$
tabs.addTab(Messages.getString("RoomFrame.TAB_PHYSICS"),makePhysicsPane()); //$NON-NLS-1$
int selectedTab = (Integer) res.get(PRoom.CURRENT_TAB);
tabs.setSelectedIndex(selectedTab);
tabs.addChangeListener(this);
res.instanceUpdateSource.addListener(this);
res.tileUpdateSource.addListener(this);
editorPane = new EditorScrollPane(editor, true);
prelf.make(editorPane,PRoomEditor.ZOOM);
// If the view tab is selected, display the first selected view centered
if (selectedTab == Room.TAB_VIEWS)
{
showSelectedView();
editor.roomVisual.setViewsVisible(true);
}
JPanel stats = makeStatsPane();
SequentialGroup orientationGroup = layout.createSequentialGroup();
if (!Prefs.rightOrientation) {
orientationGroup.addComponent(tabs,PREFERRED_SIZE,PREFERRED_SIZE,PREFERRED_SIZE);
}
orientationGroup.addGroup(layout.createParallelGroup()
/* */.addComponent(editorPane,200,640,DEFAULT_SIZE)
/* */.addComponent(stats));
if (Prefs.rightOrientation) {
orientationGroup.addComponent(tabs,PREFERRED_SIZE,PREFERRED_SIZE,PREFERRED_SIZE);
}
layout.setHorizontalGroup(layout.createParallelGroup()
/**/.addComponent(tools,PREFERRED_SIZE,PREFERRED_SIZE,MAX_VALUE)
/**/.addGroup(orientationGroup));
layout.setVerticalGroup(layout.createSequentialGroup()
/**/.addComponent(tools,PREFERRED_SIZE,PREFERRED_SIZE,PREFERRED_SIZE)
/**/.addGroup(layout.createParallelGroup()
/* */.addComponent(tabs)
/* */.addGroup(layout.createSequentialGroup()
/* */.addComponent(editorPane,DEFAULT_SIZE,480,DEFAULT_SIZE)
/* */.addComponent(stats))));
// initialize the undo/redo system
undoManager = new UndoManager();
undoManager.setLimit(Prefs.undoHistorySize);
undoSupport = new UndoableEditSupport();
undoSupport.addUndoableEditListener(new UndoAdapter());
refreshUndoRedoButtons();
if (res.get(PRoom.REMEMBER_WINDOW_SIZE))
{
int h = res.get(PRoom.EDITOR_HEIGHT);
int w = res.get(PRoom.EDITOR_WIDTH);
Dimension d = LGM.mdi.getSize();
if (d.width <= w && d.height <= h) {
maximize = true;
} else {
setSize(w, h);
}
}
else
pack();
}
private boolean maximize;
// maximizes over-sized RoomFrames, since setMaximum can't
// be called until after it's been added to the MDI
@Override
public void setVisible(boolean b)
{
super.setVisible(b);
if (!maximize) return;
try
{
setMaximum(true);
}
catch (PropertyVetoException e)
{
setSize((Integer) res.get(PRoom.EDITOR_WIDTH),(Integer) res.get(PRoom.EDITOR_HEIGHT));
e.printStackTrace();
}
}
public static class ListComponentRenderer implements ListCellRenderer<Object>
{
public Component getListCellRendererComponent(JList<? extends Object> list, Object val,
int ind, boolean selected, boolean focus)
{
Component lab = (Component) val;
if (selected)
{
lab.setBackground(list.getSelectionBackground());
lab.setForeground(list.getSelectionForeground());
}
else
{
lab.setBackground(list.getBackground());
lab.setForeground(list.getForeground());
}
return lab;
}
}
@Override
protected boolean areResourceFieldsEqual()
{
return (res.backgroundDefs.equals(resOriginal.backgroundDefs)
&& res.views.equals(resOriginal.views) && res.instances.equals(resOriginal.instances) && res.tiles.equals(resOriginal.tiles));
}
@Override
public void commitChanges()
{
res.setName(name.getText());
for (CodeFrame cf : codeFrames.values())
cf.commitChanges();
if (res.get(PRoom.REMEMBER_WINDOW_SIZE))
{
res.put(PRoom.CURRENT_TAB,tabs.getSelectedIndex());
Dimension s = getSize();
res.put(PRoom.EDITOR_WIDTH,s.width);
res.put(PRoom.EDITOR_HEIGHT,s.height);
}
}
// Window which displays the room controls
public static JFrame roomControlsFrame;
private void deleteAction()
{
deleteAction(true);
}
private void deleteAction(boolean askConfirmation)
{
boolean tilesTabIsSelected = (tabs.getSelectedIndex() == Room.TAB_TILES);
String message;
int result = 0;
if (askConfirmation)
{
// Set message
if (tilesTabIsSelected)
message = Messages.getString("RoomFrame.DELETE_TILES");
else
message = Messages.getString("RoomFrame.DELETE_OBJECTS");
// Get a confirmation from the user
result = JOptionPane.showConfirmDialog(this,message,
Messages.getString("RoomFrame.DELETE_TITLE"),JOptionPane.YES_NO_OPTION);
}
if (result == JOptionPane.YES_OPTION || askConfirmation == false)
{
Piece selectedPiece = editor.getSelectedPiece();
// If there is a selected piece, deselect it
if (selectedPiece != null) selectedPiece.setSelected(false);
Room currentRoom = editor.getRoom();
// Stores several actions in one compound action for the undo
CompoundEdit compoundEdit = new CompoundEdit();
// If the user draw a region
if (editor.selection != null)
{
Rectangle selection = editor.selection;
if (tilesTabIsSelected)
deleteTilesInSelection(selection,compoundEdit);
else
deleteInstancesInSelection(selection,compoundEdit);
}
else
{
if (tilesTabIsSelected)
{
// Record the effect of removing all tiles for the undo
for (int i = currentRoom.tiles.size() - 1; i >= 0; i--)
{
UndoableEdit edit = new RemovePieceInstance(this,(Piece) currentRoom.tiles.get(i),i);
compoundEdit.addEdit(edit);
}
// Remove all tiles
currentRoom.tiles.clear();
}
else
{
// Record the effect of removing all instances for the undo
for (int i = currentRoom.instances.size() - 1; i >= 0; i--)
{
UndoableEdit edit = new RemovePieceInstance(this,(Piece) currentRoom.instances.get(i),i);
compoundEdit.addEdit(edit);
}
// Remove all instances
currentRoom.instances.clear();
}
}
// Save the action for the undo
compoundEdit.end();
undoSupport.postEdit(compoundEdit);
}
}
// Delete all instances for a given selection
public void deleteInstancesInSelection(Rectangle selection, CompoundEdit compoundEdit)
{
Room currentRoom = editor.getRoom();
Point instancePosition;
// Remove each instance in the selection
for (int i = currentRoom.instances.size() - 1; i >= 0; i--)
{
instancePosition = currentRoom.instances.get(i).getPosition();
// If the instance is in the selected region
if (instancePosition.x >= selection.x && instancePosition.x < (selection.x + selection.width)
&& instancePosition.y >= selection.y
&& instancePosition.y < (selection.y + selection.height))
{
// Record the effect of removing an instance for the undo
UndoableEdit edit = new RemovePieceInstance(this,(Piece) currentRoom.instances.get(i),i);
compoundEdit.addEdit(edit);
currentRoom.instances.remove(i);
}
}
}
// Delete all tiles for a given selection
public void deleteTilesInSelection(Rectangle selection, CompoundEdit compoundEdit)
{
Room currentRoom = editor.getRoom();
// Get the selected layer
Integer depth = (Integer) tileLayer.getSelectedItem();
Point tilePosition;
// Remove each tile with the selected layer
for (int i = currentRoom.tiles.size() - 1; i >= 0; i--)
{
tilePosition = currentRoom.tiles.get(i).getPosition();
// If the tile is in the selected region
if (tilePosition.x >= selection.x && tilePosition.x < (selection.x + selection.width)
&& tilePosition.y >= selection.y && tilePosition.y < (selection.y + selection.height))
{
// If the were editing only the current layer, and if the tile is not in the current layer
if (!tEditOtherLayers.isSelected() && currentRoom.tiles.get(i).getDepth() != depth)
continue;
// Record the effect of removing a tile for the undo
UndoableEdit edit = new RemovePieceInstance(this,(Piece) currentRoom.tiles.get(i),i);
compoundEdit.addEdit(edit);
currentRoom.tiles.remove(i);
}
}
}
@Override
public void actionPerformed(ActionEvent e)
{
Object eventSource = e.getSource();
if (eventSource == fill)
{
// if the user didn't make any selection
if (editor.selection == null) return;
boolean tilesTabIsSelected = (tabs.getSelectedIndex() == Room.TAB_TILES);
boolean objectsTabIsSelected = (tabs.getSelectedIndex() == Room.TAB_OBJECTS);
boolean snapToGridMode = editor.properties.get(PRoomEditor.SNAP_TO_GRID);
boolean deleteUnderlyingObjects = editor.properties.get(PRoomEditor.DELETE_UNDERLYING_OBJECTS);
boolean deleteUnderlyingTiles = editor.properties.get(PRoomEditor.DELETE_UNDERLYING_TILES);
// If no object is selected
if (objectsTabIsSelected && oNew.getSelected() == null) return;
if (tilesTabIsSelected && taSource.getSelected() == null) return;
// If there is a selected piece, deselect it
if (selectedPiece != null) selectedPiece.setSelected(false);
Room currentRoom = editor.getRoom();
Rectangle selection = editor.selection;
// Get the 'snap' properties of the current room
int snapX = currentRoom.properties.get(PRoom.SNAP_X);
int snapY = currentRoom.properties.get(PRoom.SNAP_Y);
Dimension cellDimension = null;
Dimension tileDimension = null;
// Stores several actions in one compound action for the undo
CompoundEdit compoundEdit = new CompoundEdit();
// If the tiles tab is selected,
if (tilesTabIsSelected)
{
// If the 'Delete underlying' option is checked, delete all tiles for the selected region
if (deleteUnderlyingTiles) deleteTilesInSelection(selection,compoundEdit);
// Get and store the tile's dimension
ResourceReference<Background> bkg = taSource.getSelected();
Background b = bkg.get();
if (!(Boolean) b.get(PBackground.USE_AS_TILESET))
tileDimension = new Dimension(b.getWidth(),b.getHeight());
else
tileDimension = new Dimension((Integer) b.get(PBackground.TILE_WIDTH),
(Integer) b.get(PBackground.TILE_HEIGHT));
}
// If object's tab is selected and the 'Delete underlying' option is checked, delete all instances for the selected region
if (objectsTabIsSelected && deleteUnderlyingObjects)
deleteInstancesInSelection(selection,compoundEdit);
// If snapping is deactivated, use the piece's width for setting its position
if (snapToGridMode == false)
{
if (objectsTabIsSelected)
{
ResourceReference<GmObject> instanceObject = oNew.getSelected();
BufferedImage image = instanceObject.get().getDisplayImage();
// If there is no image for this instance, use the default sprite image
if (image == null)
{
ImageIcon emptySprite = LGM.getIconForKey("Resource.EMPTY_OBJ");
cellDimension = new Dimension(emptySprite.getIconWidth(),emptySprite.getIconHeight());
}
else
{
cellDimension = new Dimension(image.getWidth(),image.getHeight());
}
}
else
{
cellDimension = tileDimension;
}
}
else
{
// Use snapping for setting the piece's position
cellDimension = new Dimension(snapX,snapY);
}
int numberOfColumns = editor.selection.width / cellDimension.width;
int numberOfRows = editor.selection.height / cellDimension.height;
// Browse each cell of the selected region
for (int i = 0; i < numberOfColumns; i++)
for (int j = 0; j < numberOfRows; j++)
{
// Position of the current piece
Point newPosition = new Point(selection.x + (cellDimension.width * i),selection.y
+ (cellDimension.height * j));
// If object's tab is selected, add a new object
if (objectsTabIsSelected)
{
Instance newInstance = res.addInstance();
newInstance.properties.put(PInstance.OBJECT,oNew.getSelected());
newInstance.setPosition(newPosition);
// Record the effect of adding a new instance for the undo
UndoableEdit edit = new AddPieceInstance(this,newInstance,
currentRoom.instances.size() - 1);
compoundEdit.addEdit(edit);
}
// If the tile's tab is selected, add a new tile
if (tilesTabIsSelected)
{
ResourceReference<Background> bkg = taSource.getSelected();
Tile newTile = new Tile(currentRoom,LGM.currentFile);
newTile.properties.put(PTile.BACKGROUND,bkg);
newTile.setBackgroundPosition(new Point(tSelect.tx,tSelect.ty));
newTile.setPosition(newPosition);
newTile.setSize(tileDimension);
newTile.setDepth((Integer) tileLayer.getSelectedItem());
currentRoom.tiles.add(newTile);
// Record the effect of adding a new tile for the undo
UndoableEdit edit = new AddPieceInstance(this,newTile,currentRoom.tiles.size() - 1);
compoundEdit.addEdit(edit);
}
}
// Save the action for the undo
compoundEdit.end();
undoSupport.postEdit(compoundEdit);
}
// If the user has pressed the 'Add' new layer button
if (eventSource == addLayer)
{
// Create the panel with the depth property
JPanel myPanel = new JPanel();
myPanel.add(new JLabel(Messages.getString("RoomFrame.TILE_DEPTH")));
NumberField depth = new NumberField(Integer.MIN_VALUE,Integer.MAX_VALUE,0);
myPanel.add(depth);
int result = JOptionPane.showConfirmDialog(this,myPanel,
Messages.getString("RoomFrame.ADD_NEW_TILE"),JOptionPane.OK_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE);
// If the user has pressed the OK button
if (result == JOptionPane.OK_OPTION)
{
// Get the new layer's depth
Integer newDepth = new Integer(depth.getIntValue());
// If the layer is new, add it
if (!layers.contains(newDepth))
{
layers.add(newDepth);
// Sort the layers in descending order
Collections.sort(layers,Collections.reverseOrder());
// Select the new layer
tileLayer.setSelectedItem(newDepth);
}
}
}
// If the user has pressed the 'delete' tile's layer button
if (eventSource == deleteLayer)
{
// Get a confirmation from the user
int result = JOptionPane.showConfirmDialog(this,
Messages.getString("RoomFrame.DELETE_TILE_LAYER"),
Messages.getString("RoomFrame.DELETE_TITLE"),JOptionPane.YES_NO_OPTION);
if (result == JOptionPane.YES_OPTION)
{
Room currentRoom = editor.getRoom();
// Get the selected layer
Integer depth = (Integer) tileLayer.getSelectedItem();
// Stores several actions in one compound action for the undo
CompoundEdit compoundEdit = new CompoundEdit();
// Remove each tile with the selected layer
for (int i = currentRoom.tiles.size() - 1; i >= 0; i--)
{
if (currentRoom.tiles.get(i).getDepth() == depth)
{
// Record the effect of removing a tile for the undo
UndoableEdit edit = new RemovePieceInstance(this,(Piece) currentRoom.tiles.get(i),i);
compoundEdit.addEdit(edit);
currentRoom.tiles.remove(i);
}
}
// Save the action for the undo
compoundEdit.end();
undoSupport.postEdit(compoundEdit);
// Remove the layer from the combo box
layers.remove(depth);
if (layers.size() == 0) layers.add(0);
tileLayer.setSelectedIndex(0);
}
}
// If the user has pressed the 'Change' tile's layer button
if (eventSource == changeLayer)
{
JPanel myPanel = new JPanel();
myPanel.add(new JLabel(Messages.getString("RoomFrame.TILE_DEPTH")));
// Get the selected layer
final Integer depth = (Integer) tileLayer.getSelectedItem();
NumberField depthField = new NumberField(Integer.MIN_VALUE,Integer.MAX_VALUE,depth);
myPanel.add(depthField);
int result = JOptionPane.showConfirmDialog(this,myPanel,
Messages.getString("RoomFrame.CHANGE_TILE_LAYER"),JOptionPane.OK_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE);
// Get the new layer's depth
final Integer newDepth = new Integer(depthField.getIntValue());
if (result == JOptionPane.OK_OPTION && newDepth != depth)
{
Room currentRoom = editor.getRoom();
// Stores several actions in one compound action for the undo
//CompoundEdit compoundEdit = new CompoundEdit();
// Update each tile with the selected layer
for (int i = currentRoom.tiles.size() - 1; i >= 0; i--)
{
final Tile tile = currentRoom.tiles.get(i);
if (tile.getDepth() == depth)
{
tile.setDepth(newDepth);
}
}
//TODO: Save the action for the undo
//compoundEdit.end();
//undoSupport.postEdit(compoundEdit);
// Replace the layer from the combo box
layers.remove(depth);
if (!layers.contains(newDepth)) layers.add(newDepth);
// Sort the layers in descending order
Collections.sort(layers,Collections.reverseOrder());
// Select the new layer
tileLayer.setSelectedItem(newDepth);
}
}
// If the user has clicked on the 'Edit other layers' checkbox
if (eventSource == tEditOtherLayers)
{
if (tEditOtherLayers.isSelected())
editor.editOtherLayers(true);
else
editor.editOtherLayers(false);
}
// If the user has clicked on the 'Hide other layers' checkbox
if (eventSource == tHideOtherLayers)
{
if (tHideOtherLayers.isSelected())
editor.roomVisual.setVisibleLayer((Integer) tileLayer.getSelectedItem());
else
editor.roomVisual.setVisibleLayer(null);
}
// If the user has pressed the 'room controls' button
if (eventSource == roomControls)
{
// If the window is not open
if (roomControlsFrame == null)
{
// Create a window and set the properties
roomControlsFrame = new JFrame(Messages.getString("RoomControls.TITLE"));
roomControlsFrame.setIconImage(LGM.getIconForKey("RoomFrame.ROOM_CONTROLS").getImage());
Border padding = BorderFactory.createEmptyBorder(15,15,15,15);
JPanel contentPanel = new JPanel();
contentPanel.setBorder(padding);
roomControlsFrame.setContentPane(contentPanel);
roomControlsFrame.setLayout(new BoxLayout(roomControlsFrame.getContentPane(),
BoxLayout.Y_AXIS));
roomControlsFrame.setResizable(false);
roomControlsFrame.setLocationRelativeTo(null);
// Add the labels
roomControlsFrame.add(new JLabel(Messages.getString("RoomControls.LEFT_BUTTON")));
roomControlsFrame.add(new JLabel(Messages.getString("RoomControls.LEFT_BUTTON_CTRl")));
roomControlsFrame.add(new JLabel(Messages.getString("RoomControls.LEFT_BUTTON_ALT")));
roomControlsFrame.add(new JLabel(Messages.getString("RoomControls.LEFT_BUTTON_SHIFT")));
roomControlsFrame.add(Box.createRigidArea(new Dimension(0,5)));
roomControlsFrame.add(new JLabel(Messages.getString("RoomControls.RIGHT_BUTTON")));
// When closing the window, set the window to null
roomControlsFrame.addWindowListener(new java.awt.event.WindowAdapter()
{
@Override
public void windowClosing(java.awt.event.WindowEvent windowEvent)
{
roomControlsFrame = null;
}
});
roomControlsFrame.pack();
roomControlsFrame.setVisible(true);
}
else
{
// Make sure the window is visible and not minimized
roomControlsFrame.setState(Frame.NORMAL);
roomControlsFrame.setVisible(true);
}
}
// If the user has pressed the shift instances button
if (eventSource == shiftInstances)
{
Room currentRoom = editor.getRoom();
// Get the 'snap' properties of the current room
int snapX = currentRoom.properties.get(PRoom.SNAP_X);
int snapY = currentRoom.properties.get(PRoom.SNAP_Y);
// Display the text fields with the snap properties
NumberField txtHorizontalShift = new NumberField(-999999,999999,snapX);
NumberField txtVerticalShift = new NumberField(-999999,999999,snapY);
// Create the panel with the shift properties
JPanel myPanel = new JPanel();
myPanel.add(new JLabel(Messages.getString("RoomFrame.HORIZONTAL_SHIFT")));
myPanel.add(txtHorizontalShift);
myPanel.add(Box.createHorizontalStrut(7));
myPanel.add(new JLabel(Messages.getString("RoomFrame.VERTICAL_SHIFT")));
myPanel.add(txtVerticalShift);
// If the tiles tab is selected, shift the tiles
boolean tilesTabIsSelected = (tabs.getSelectedIndex() == Room.TAB_TILES);
String panelTitle;
// Set the panel title
if (tilesTabIsSelected)
panelTitle = Messages.getString("RoomFrame.SHIFT_TILES_TITLE");
else
panelTitle = Messages.getString("RoomFrame.SHIFT_OBJECTS_TITLE");
int result = JOptionPane.showConfirmDialog(this,myPanel,panelTitle,
JOptionPane.OK_CANCEL_OPTION,JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION)
{
// If there is no tiles to shift
if (currentRoom.tiles.size() == 0 && tilesTabIsSelected) return;
// If there is no objects to shift
if (currentRoom.instances.size() == 0 && tilesTabIsSelected == false) return;
// Get the shift values
int horizontalShift = txtHorizontalShift.getIntValue();
int verticalShift = txtVerticalShift.getIntValue();
// If the position is the same
if (horizontalShift == 0 & verticalShift == 0) return;
Piece selectedPiece = editor.getSelectedPiece();
// If there is a selected piece, deselect it
if (selectedPiece != null) selectedPiece.setSelected(false);
// If the tiles tab is selected, shift the tiles
if (tilesTabIsSelected)
{
for (Tile tile : currentRoom.tiles)
{
// Select the instance in the list, otherwise it is sometimes not correctly selected
tList.setSelectedValue(tile,false);
Point newPosition = new Point(tile.getPosition().x + horizontalShift,
tile.getPosition().y + verticalShift);
tile.setPosition(newPosition);
}
}
else
// Shift the objects
{
for (Instance instance : currentRoom.instances)
{
// Select the instance in the list, otherwise it is sometimes not correctly selected
oList.setSelectedValue(instance,false);
Point newPosition = new Point(instance.getPosition().x + horizontalShift,
instance.getPosition().y + verticalShift);
instance.setPosition(newPosition);
}
}
// Record the effect of shifting instances for the undo
UndoableEdit edit = new ShiftPieceInstances(this,tilesTabIsSelected,horizontalShift,
verticalShift);
// notify the listeners
undoSupport.postEdit(edit);
}
return;
}
if (eventSource == showButton)
{
showMenu.show(showButton,0,showButton.getHeight());
return;
}
// If the user has pressed the 'Add' object button
if (eventSource == addObjectButton)
{
// If no object is selected
if (oNew.getSelected() == null) return;
Piece selectedPiece = editor.getSelectedPiece();
// If there is a selected piece, deselect it
if (selectedPiece != null) selectedPiece.setSelected(false);
// Add the new object instance
Instance newObject = res.addInstance();
newObject.properties.put(PInstance.OBJECT,oNew.getSelected());
newObject.setPosition(new Point());
int numberOfObjects = res.instances.size();
// Record the effect of adding an object for the undo
UndoableEdit edit = new AddPieceInstance(this,newObject,numberOfObjects - 1);
// notify the listeners
undoSupport.postEdit(edit);
oList.setSelectedIndex(numberOfObjects - 1);
return;
}
// If the user has pressed the 'Delete' object button
if (eventSource == deleteObjectButton)
{
int selectedIndex = oList.getSelectedIndex();
if (selectedIndex == -1) return;
Instance instance = oList.getSelectedValue();
if (instance == null) return;
Piece selectedPiece = editor.getSelectedPiece();
// If there is a selected piece, deselect it
if (selectedPiece != null) selectedPiece.setSelected(false);
// Record the effect of removing an object for the undo
UndoableEdit edit = new RemovePieceInstance(this,instance,selectedIndex);
// notify the listeners
undoSupport.postEdit(edit);
CodeFrame codeFrame = codeFrames.get(res.instances.remove(selectedIndex));
if (codeFrame != null) codeFrame.dispose();
oList.setSelectedIndex(Math.min(res.instances.size() - 1,selectedIndex));
return;
}
if (eventSource == taSource)
{
tSelect.setBackground(taSource.getSelected());
return;
}
// If the user has pressed the 'Delete' tile button
if (eventSource == deleteTileButton)
{
int selectedIndex = tList.getSelectedIndex();
if (selectedIndex >= res.tiles.size() || selectedIndex < 0) return;
Piece selectedPiece = editor.getSelectedPiece();
// If there is a selected piece, deselect it
if (selectedPiece != null) selectedPiece.setSelected(false);
Tile tile = tList.getSelectedValue();
// Record the effect of removing an object for the undo
UndoableEdit edit = new RemovePieceInstance(this,tile,selectedIndex);
// notify the listeners
undoSupport.postEdit(edit);
res.tiles.remove(selectedIndex);
tList.setSelectedIndex(Math.min(res.tiles.size() - 1,selectedIndex));
return;
}
if (e.getSource() == sCreationCode)
{
openRoomCreationCode();
return;
}
if (e.getSource() == oCreationCode)
{
if (lastObj != null) openInstanceCodeFrame(lastObj);
return;
}
super.actionPerformed(e);
}
public void fireObjUpdate()
{
Instance selectedInstance = oList.getSelectedValue();
if (lastObj == selectedInstance) return;
lastObj = selectedInstance;
PropertyLink.removeAll(loLocked,loSource,loName,loX,loY,loScaleX,loScaleY,loColour,loRotation,loAlpha);
if (selectedInstance != null)
{
PropertyLinkFactory<PInstance> iplf = new PropertyLinkFactory<PInstance>(
selectedInstance.properties,this);
loLocked = iplf.make(oLocked,PInstance.LOCKED);
loSource = iplf.make(oSource,PInstance.OBJECT);
loName = iplf.make(objectName.getDocument(), PInstance.NAME);
loX = iplf.make(objectHorizontalPosition,PInstance.X);
loY = iplf.make(objectVerticalPosition,PInstance.Y);
loScaleX = iplf.make(objectScaleX,PInstance.SCALE_X);
loScaleY = iplf.make(objectScaleY,PInstance.SCALE_Y);
loRotation = iplf.make(objectRotation,PInstance.ROTATION);
loColour = iplf.make(objectColor,PInstance.COLOR);
loAlpha = iplf.make(objectAlpha,PInstance.ALPHA);
}
}
@Override
public Dimension getMinimumSize()
{
Dimension p = getContentPane().getSize();
Dimension l = getContentPane().getMinimumSize();
Dimension s = getSize();
l.width += s.width - p.width;
l.height += s.height - p.height;
return l;
}
public void fireTileUpdate()
{
Tile selectedTile = tList.getSelectedValue();
if (lastTile == selectedTile) return;
lastTile = selectedTile;
PropertyLink.removeAll(ltDepth,ltLocked,ltSource,ltsX,ltsY,ltX,ltY);
if (selectedTile != null)
{
PropertyLinkFactory<PTile> tplf = new PropertyLinkFactory<PTile>(selectedTile.properties,this);
ltDepth = tplf.make(teDepth,PTile.DEPTH);
ltLocked = tplf.make(tLocked,PTile.LOCKED);
ltSource = tplf.make(teSource,PTile.BACKGROUND);
ltsX = tplf.make(tsX,PTile.BG_X);
ltsY = tplf.make(tsY,PTile.BG_Y);
ltX = tplf.make(tileHorizontalPosition,PTile.ROOM_X);
ltY = tplf.make(tileVerticalPosition,PTile.ROOM_Y);
}
}
public void fireBackUpdate()
{
int i = bList.getSelectedIndex();
if (lastValidBack == i) return;
if (i < 0)
{
bList.setSelectedIndex(lastValidBack < 0 ? 0 : lastValidBack);
return;
}
lastValidBack = i;
PropertyLink.removeAll(lbVisible,lbForeground,lbSource,lbX,lbY,lbTileH,lbTileV,lbStretch,lbH,
lbV);
BackgroundDef b = res.backgroundDefs.get(i);
PropertyLinkFactory<PBackgroundDef> bdplf = new PropertyLinkFactory<PBackgroundDef>(
b.properties,this);
lbVisible = bdplf.make(bVisible,PBackgroundDef.VISIBLE);
lbForeground = bdplf.make(bForeground,PBackgroundDef.FOREGROUND);
lbSource = bdplf.make(bSource,PBackgroundDef.BACKGROUND);
lbX = bdplf.make(bX,PBackgroundDef.X);
lbY = bdplf.make(bY,PBackgroundDef.Y);
lbTileH = bdplf.make(bTileH,PBackgroundDef.TILE_HORIZ);
lbTileV = bdplf.make(bTileV,PBackgroundDef.TILE_VERT);
lbStretch = bdplf.make(bStretch,PBackgroundDef.STRETCH);
lbH = bdplf.make(bH,PBackgroundDef.H_SPEED);
lbV = bdplf.make(bV,PBackgroundDef.V_SPEED);
}
public void fireViewUpdate()
{
int i = vList.getSelectedIndex();
if (lastValidView == i) return;
if (i < 0)
{
bList.setSelectedIndex(lastValidView < 0 ? 0 : lastValidView);
return;
}
lastValidView = i;
PropertyLink.removeAll(lvVisible,lvRX,lvRY,lvRW,lvRH,lvPX,lvPY,lvPW,lvPH,lvObj,lvOHBor,lvOVBor,
lvOHSp,lvOVSp);
View view = res.views.get(i);
PropertyLinkFactory<PView> vplf = new PropertyLinkFactory<PView>(view.properties,this);
lvVisible = vplf.make(vVisible,PView.VISIBLE);
lvRX = vplf.make(vRX,PView.VIEW_X);
lvRY = vplf.make(vRY,PView.VIEW_Y);
lvRW = vplf.make(vRW,PView.VIEW_W);
lvRH = vplf.make(vRH,PView.VIEW_H);
lvPX = vplf.make(vPX,PView.PORT_X);
lvPY = vplf.make(vPY,PView.PORT_Y);
lvPW = vplf.make(vPW,PView.PORT_W);
lvPH = vplf.make(vPH,PView.PORT_H);
lvObj = vplf.make(vObj,PView.OBJECT);
lvOHBor = vplf.make(vOHBor,PView.BORDER_H);
lvOVBor = vplf.make(vOVBor,PView.BORDER_V);
lvOHSp = vplf.make(vOHSp,PView.SPEED_H);
lvOVSp = vplf.make(vOVSp,PView.SPEED_V);
}
// Display the selected tile with a border and centered in the editor window
private void showSelectedTile()
{
Piece selectedPiece = editor.getSelectedPiece();
// If there is a selected piece, deselect it
if (selectedPiece != null) selectedPiece.setSelected(false);
// Display the selected tile with white border
Tile tile = tList.getSelectedValue();
if (tile == null) return;
tile.setSelected(true);
// Save the selected tile
editor.setSelectedPiece(tile);
Point tilePosition = tile.getPosition();
centerObjectInViewport(tilePosition,tile.getSize().width,tile.getSize().height,null);
}
// Display the selected instance with a border and centered in the editor window
private void showSelectedInstance()
{
Piece selectedPiece = editor.getSelectedPiece();
// If there is a selected piece, deselect it
if (selectedPiece != null) selectedPiece.setSelected(false);
// Display the selected instance with white border
Instance instance = oList.getSelectedValue();
if (instance == null)
{
return;
}
instance.setSelected(true);
// Save the selected instance
editor.setSelectedPiece(instance);
Point instancePosition = instance.getPosition();
// Get the image dimension
ResourceReference<GmObject> instanceObject = instance.properties.get(PInstance.OBJECT);
BufferedImage instanceImage = null;
if (instanceObject != null)
{
GmObject inst = instanceObject.get();
if (inst != null) instanceImage = inst.getDisplayImage();
}
if (instanceImage == null)
{
ImageIcon emptySprite = LGM.getIconForKey("Resource.EMPTY_OBJ");
centerObjectInViewport(instancePosition, emptySprite.getIconWidth(),
emptySprite.getIconHeight(), null);
}
else
{
centerObjectInViewport(instancePosition, instanceImage.getWidth(), instanceImage.getHeight(),
null);
}
}
// Center an object in the viewport of the rooms editor
private void centerObjectInViewport(Point objectPosition, int objectWidth, int objectHeight,
Instance instanceToFollow)
{
JViewport viewport = editorPane.getViewport();
Point newViewportPosition = new Point(0,0);
int zoomLevel = editor.properties.get(PRoomEditor.ZOOM);
// Viewport scale when zooming out
int viewportScale = 0;
if (zoomLevel == -1) viewportScale = 3;
if (zoomLevel == 0) viewportScale = 2;
// If we are zooming out
if (zoomLevel < 1)
{
newViewportPosition.x = objectPosition.x
- (viewport.getWidth() * viewportScale - objectWidth) / 2;
newViewportPosition.y = objectPosition.y
- (viewport.getHeight() * viewportScale - objectHeight) / 2;
}
else
{
newViewportPosition.x = objectPosition.x - (viewport.getWidth() - objectWidth * zoomLevel)
/ (2 * zoomLevel);
newViewportPosition.y = objectPosition.y - (viewport.getHeight() - objectHeight * zoomLevel)
/ (2 * zoomLevel);
}
// If the new position of the object is above the room origin coordinates, use the room coordinates for the new object coordinates
if (newViewportPosition.x < editor.getOverallBounds().x)
newViewportPosition.x = editor.getOverallBounds().x;
if (newViewportPosition.y < editor.getOverallBounds().y)
newViewportPosition.y = editor.getOverallBounds().y;
if (instanceToFollow == null)
{
// If the object position is above the viewport coordinates, use the object coordinates for the new viewport coordinates
if (objectPosition.x < newViewportPosition.x) newViewportPosition.x = objectPosition.x;
if (objectPosition.y < newViewportPosition.y) newViewportPosition.y = objectPosition.x;
}
// For the new viewport position, take into account the visual offset of the border and the zoom level
editor.visualToComponent(newViewportPosition);
viewport.setViewPosition(newViewportPosition);
}
// Display the selected view in the center of the window
private void showSelectedView()
{
if (editorPane == null) return;
Room currentRoom = editor.getRoom();
// If the views are not enabled
if ((Boolean) currentRoom.get(PRoom.VIEWS_ENABLED) == false) return;
// Get the selected view
View view = res.views.get(vList.getSelectedIndex());
// If the view is not visible, don't show it
if ((Boolean) view.properties.get(PView.VISIBLE) == false) return;
// Get the reference to the 'Object following' object
ResourceReference<GmObject> objectToFollowReference = null;
// If there is 'Object following' object for the selected view
if (view.properties.get(PView.OBJECT) != null)
objectToFollowReference = view.properties.get(PView.OBJECT);
Instance instanceToFollow = null;
// If there is an object to follow, get the first instance in the room
if (objectToFollowReference != null)
{
for (Instance instance : currentRoom.instances)
{
ResourceReference<GmObject> instanceObject = instance.properties.get(PInstance.OBJECT);
if (instanceObject == objectToFollowReference)
{
instanceToFollow = instance;
break;
}
}
}
// Properties of the view
Point viewPosition = new Point(0,0);
int viewWidth = (Integer) view.properties.get(PView.VIEW_W);
int viewHeight = (Integer) view.properties.get(PView.VIEW_H);
// If there is an instance to follow, use the instance properties for centering the view
if (instanceToFollow != null)
{
// Get the instance position
Point instancePosition = new Point(0,0);
instancePosition.x = (Integer) instanceToFollow.properties.get(PInstance.X);
instancePosition.y = (Integer) instanceToFollow.properties.get(PInstance.Y);
viewPosition.x = instancePosition.x - viewWidth / 2;
viewPosition.y = instancePosition.y - viewHeight / 2;
// Set this new location into the view properties
view.properties.put(PView.OBJECT_FOLLOWING_X,viewPosition.x);
view.properties.put(PView.OBJECT_FOLLOWING_Y,viewPosition.y);
}
else
{
// Get the properties of the view
viewPosition.x = view.properties.get(PView.VIEW_X);
viewPosition.y = view.properties.get(PView.VIEW_Y);
view.properties.put(PView.OBJECT_FOLLOWING_X,-1);
view.properties.put(PView.OBJECT_FOLLOWING_Y,-1);
}
centerObjectInViewport(viewPosition,viewWidth,viewHeight,instanceToFollow);
}
// if an item of a listbox has been selected
public void valueChanged(ListSelectionEvent e)
{
if (e.getValueIsAdjusting()) return;
if (e.getSource() == oList) fireObjUpdate();
if (e.getSource() == tList) fireTileUpdate();
if (e.getSource() == bList) fireBackUpdate();
if (e.getSource() == vList)
{
fireViewUpdate();
showSelectedView();
}
}
public CodeFrame openCodeFrame(CodeHolder code, String titleFormat, Object titleArg)
{
CodeFrame frame = codeFrames.get(code);
if (frame == null)
{
frame = new CodeFrame(code,titleFormat,titleArg);
codeFrames.put(code,frame);
frame.addInternalFrameListener(new InternalFrameAdapter()
{
@Override
public void internalFrameClosed(InternalFrameEvent e)
{
CodeFrame f = ((CodeFrame) e.getSource());
codeFrames.remove(f.codeHolder);
f.removeInternalFrameListener(this);
}
});
LGM.mdi.add(frame);
LGM.mdi.addZChild(this,frame);
frame.toTop();
}
else
frame.toTop();
return frame;
}
public CodeFrame openInstanceCodeFrame(Instance inst)
{
return openCodeFrame(inst,Messages.getString("RoomFrame.TITLE_FORMAT_CREATION"),
Messages.format("RoomFrame.INSTANCE",inst.properties.get(PInstance.ID)));
}
public CodeFrame openInstanceCodeFrame(int id, boolean select)
{
Instance inst = findInstance(id,select);
if (inst != null)
{
return openCodeFrame(inst,Messages.getString("RoomFrame.TITLE_FORMAT_CREATION"),
Messages.format("RoomFrame.INSTANCE",inst.properties.get(PInstance.ID)));
}
return null;
}
public CodeFrame openRoomCreationCode()
{
return openCodeFrame(res,Messages.getString("RoomFrame.TITLE_FORMAT_CREATION"),res.getName()); //$NON-NLS-1$
}
public Instance findInstance(int id, boolean select)
{
ListModel<Instance> model = oList.getModel();
for (int i = 0; i < model.getSize(); i++)
{
Instance inst = model.getElementAt(i);
if (inst.getID() == id)
{
if (select)
{
oList.setSelectedIndex(i);
}
return inst;
}
}
return null;
}
@Override
public void removeUpdate(DocumentEvent e)
{
CodeFrame f = codeFrames.get(res);
if (f != null) f.setTitleFormatArg(name.getText());
super.removeUpdate(e);
}
@Override
public void insertUpdate(DocumentEvent e)
{
CodeFrame f = codeFrames.get(res);
if (f != null) f.setTitleFormatArg(name.getText());
super.insertUpdate(e);
}
@Override
public void dispose()
{
Piece selectedPiece = editor.getSelectedPiece();
// If there is a selected piece, deselect it
if (selectedPiece != null) selectedPiece.setSelected(false);
super.dispose();
for (CodeFrame cf : codeFrames.values())
cf.dispose();
// XXX: These components could still be referenced by InputContext or similar.
// Removing their references to this frame is therefore necessary in order to ensure
// garbage collection.
oNew.removeActionListener(this);
oList.removeListSelectionListener(this);
addObjectButton.removeActionListener(this);
deleteObjectButton.removeActionListener(this);
oCreationCode.removeActionListener(this);
sCreationCode.removeActionListener(this);
showButton.removeActionListener(this);
taSource.removeActionListener(this);
tList.removeListSelectionListener(this);
deleteTileButton.removeActionListener(this);
bList.removeListSelectionListener(this);
vList.removeListSelectionListener(this);
editorPane.setViewport(null);
setLayout(null);
}
public void updated(UpdateEvent e)
{
if (e.source == res.instanceUpdateSource)
oList.setPrototypeCellValue(null);
else if (e.source == res.tileUpdateSource) tList.setPrototypeCellValue(null);
}
private void bdvListUpdate(boolean isBgDef, UpdateSource s, boolean v)
{
int ls = (isBgDef ? res.backgroundDefs : res.views).size();
for (int i = 0; i < ls; i++)
{
UpdateSource s2 = (isBgDef ? res.backgroundDefs.get(i).properties
: res.views.get(i).properties).updateSource;
if (s2 != s) continue;
JList<?> l = isBgDef ? bList : vList;
JLabel ll = (JLabel) l.getModel().getElementAt(i);
ll.setFont(ll.getFont().deriveFont(v ? Font.BOLD : Font.PLAIN));
l.setPrototypeCellValue(null);
break;
}
}
private class BgDefPropertyListener extends PropertyUpdateListener<PBackgroundDef>
{
@Override
public void updated(PropertyUpdateEvent<PBackgroundDef> e)
{
if (e.key == PBackgroundDef.VISIBLE) bdvListUpdate(true,e.source,(Boolean) e.map.get(e.key));
}
}
private class ViewPropertyListener extends PropertyUpdateListener<PView>
{
@Override
public void updated(PropertyUpdateEvent<PView> e)
{
if (e.key == PView.VISIBLE) bdvListUpdate(false,e.source,(Boolean) e.map.get(e.key));
// If the 'Object following' object has been changed, update the display of the view
if (e.key == PView.OBJECT || e.key == PView.VISIBLE) showSelectedView();
// If we are modifying the view dimension
if (e.key == PView.VIEW_W || e.key == PView.VIEW_H || e.key == PView.BORDER_H
|| e.key == PView.BORDER_V)
{
// Get the selected view
View view = res.views.get(vList.getSelectedIndex());
// If there is 'Object following' object for the selected view, update the display of the view
if (view.properties.get(PView.OBJECT) != null) showSelectedView();
}
}
}
// When a resource has been updated, reset the undo manager
public void resetUndoManager()
{
undoManager.discardAllEdits();
refreshUndoRedoButtons();
}
/**
* An undo/redo adapter. The adapter is notified when an undo edit occur(e.g. add or remove from the list)
* The adapter extract the edit from the event, add it to the UndoManager, and refresh the GUI
*/
private class UndoAdapter implements UndoableEditListener
{
public void undoableEditHappened(UndoableEditEvent evt)
{
UndoableEdit edit = evt.getEdit();
undoManager.addEdit(edit);
refreshUndoRedoButtons();
}
}
/**
* This method is called after each undoable operation
* in order to refresh the presentation state of the undo/redo GUI
*/
public void refreshUndoRedoButtons()
{
// refresh undo
undo.setEnabled(undoManager.canUndo());
// refresh redo
redo.setEnabled(undoManager.canRedo());
}
// When a text field related to a piece property gains the focus
public void focusGained(FocusEvent event)
{
pieceOriginalPosition = null;
pieceOriginalScale = null;
pieceOriginalRotation = null;
pieceOriginalAlpha = null;
selectedPiece = null;
// If we are modifying objects
if (event.getSource() == objectName || event.getSource() == objectHorizontalPosition
|| event.getSource() == objectVerticalPosition || event.getSource() == objectScaleX
|| event.getSource() == objectScaleY || event.getSource() == objectRotation
|| event.getSource() == objectAlpha)
{
// If no object is selected, return
int selectedIndex = oList.getSelectedIndex();
if (selectedIndex == -1) return;
// Save the selected instance
selectedPiece = oList.getSelectedValue();
// If we are modifying the name, save it for the undo
if (event.getSource() == objectName)
{
pieceOriginalName = selectedPiece.getName();
return;
}
// If we are modifying the position, save it for the undo
if (event.getSource() == objectHorizontalPosition
|| event.getSource() == objectVerticalPosition)
{
pieceOriginalPosition = new Point(selectedPiece.getPosition());
return;
}
// If we are modifying the scale, save it for the undo
if (event.getSource() == objectScaleX || event.getSource() == objectScaleY)
{
Point2D newScale = selectedPiece.getScale();
pieceOriginalScale = new Point2D.Double(newScale.getX(),newScale.getY());
return;
}
// If we are modifying the rotation, save it for the undo
if (event.getSource() == objectRotation)
{
pieceOriginalRotation = new Double(selectedPiece.getRotation());
return;
}
// If we are modifying the alpha, save it for the undo
if (event.getSource() == objectAlpha)
{
pieceOriginalAlpha = new Integer(selectedPiece.getAlpha());
return;
}
}
// We are modifying tiles
else
{
// If no tile is selected, return
int selectedIndex = tList.getSelectedIndex();
if (selectedIndex == -1) return;
// Save the selected tile
selectedPiece = tList.getSelectedValue();
// Save the position of the tile for the undo
pieceOriginalPosition = new Point(selectedPiece.getPosition());
}
}
// When a text field related to a piece position has lost the focus
public void focusLost(FocusEvent event)
{
processFocusLost();
}
// Save the position of a piece for the undo
public void processFocusLost()
{
if (selectedPiece == null) return;
// If we are modifying objects
if (selectedPiece instanceof Instance)
{
// If no object is selected, return
int selectedIndex = oList.getSelectedIndex();
if (selectedIndex == -1) return;
// If we have changed the name
if (pieceOriginalName != null)
{
// Get the new name of the object
String objectNewName = new String(selectedPiece.getName());
// If the rotation of the object has been changed
if (objectNewName != pieceOriginalName)
{
// Record the effect of rotating an object for the undo
UndoableEdit edit = new ModifyPieceInstance(this,selectedPiece,pieceOriginalName,
objectNewName);
// notify the listeners
undoSupport.postEdit(edit);
}
}
// If we have changed the position
if (pieceOriginalPosition != null)
{
// Get the new position of the object
Point objectNewPosition = new Point(selectedPiece.getPosition());
// If the position of the object has been changed
if (!objectNewPosition.equals(pieceOriginalPosition))
{
// Record the effect of moving an object for the undo
UndoableEdit edit = new ModifyPieceInstance(this,selectedPiece,pieceOriginalPosition,
objectNewPosition);
// notify the listeners
undoSupport.postEdit(edit);
}
}
// If we have changed the scale
if (pieceOriginalScale != null)
{
// Get the new scale of the object
Point2D objectNewScale = selectedPiece.getScale();
// If the scale of the object has been modified
if (!objectNewScale.equals(pieceOriginalScale))
{
// Record the effect of modifying the scale an object for the undo
UndoableEdit edit = new ModifyPieceInstance(this,selectedPiece,pieceOriginalScale,
new Point2D.Double(objectNewScale.getX(),objectNewScale.getY()));
// notify the listeners
undoSupport.postEdit(edit);
}
}
// If we have changed the rotation
if (pieceOriginalRotation != null)
{
// Get the new rotation of the object
Double objectNewRotation = new Double(selectedPiece.getRotation());
// If the rotation of the object has been changed
if (objectNewRotation != pieceOriginalRotation)
{
// Record the effect of rotating an object for the undo
UndoableEdit edit = new ModifyPieceInstance(this,selectedPiece,pieceOriginalRotation,
objectNewRotation);
// notify the listeners
undoSupport.postEdit(edit);
}
}
// If we have changed the alpha value
if (pieceOriginalAlpha != null)
{
// Get the new alpha of the object
Integer objectNewAlpha = new Integer(selectedPiece.getAlpha());
// If the alpha value of the object has been changed
if (objectNewAlpha != pieceOriginalAlpha)
{
// Record the effect of modifying the alpha value of an object for the undo
UndoableEdit edit = new ModifyPieceInstance(this,selectedPiece,pieceOriginalAlpha,
objectNewAlpha);
// notify the listeners
undoSupport.postEdit(edit);
}
}
}
// We are modifying tiles
else
{
// If no tile is selected, return
int selectedIndex = tList.getSelectedIndex();
if (selectedIndex == -1) return;
// Get the new position of the tile
Point tileNewPosition = new Point(selectedPiece.getPosition());
// If the position of the tile has been changed
if (!tileNewPosition.equals(pieceOriginalPosition))
{
// Record the effect of moving an tile for the undo
UndoableEdit edit = new ModifyPieceInstance(this,selectedPiece,pieceOriginalPosition,
tileNewPosition);
// notify the listeners
undoSupport.postEdit(edit);
}
}
selectedPiece = null;
}
// When a new tab is selected
public void stateChanged(ChangeEvent event)
{
// If the views tab is selected, always display the views
if (tabs.getSelectedIndex() == Room.TAB_VIEWS)
{
showSelectedView();
editor.roomVisual.setViewsVisible(true);
}
else
{
editor.roomVisual.setViewsVisible(false);
}
}
}