0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.modules.vmd.game.editor.tiledlayer;
0043:
0044: import java.awt.Color;
0045: import java.awt.Cursor;
0046: import java.awt.Dialog;
0047: import java.awt.Dimension;
0048: import java.awt.Graphics;
0049: import java.awt.Graphics2D;
0050: import java.awt.Image;
0051: import java.awt.Point;
0052: import java.awt.Rectangle;
0053: import java.awt.Toolkit;
0054: import java.awt.datatransfer.Transferable;
0055: import java.awt.datatransfer.UnsupportedFlavorException;
0056: import java.awt.dnd.DnDConstants;
0057: import java.awt.dnd.DropTarget;
0058: import java.awt.dnd.DropTargetDragEvent;
0059: import java.awt.dnd.DropTargetDropEvent;
0060: import java.awt.dnd.DropTargetEvent;
0061: import java.awt.dnd.DropTargetListener;
0062: import java.awt.event.ActionEvent;
0063: import java.awt.event.ItemEvent;
0064: import java.awt.event.ItemListener;
0065: import java.awt.event.ItemListener;
0066: import java.awt.event.MouseEvent;
0067: import java.awt.event.MouseListener;
0068: import java.awt.event.MouseMotionAdapter;
0069: import java.awt.event.MouseMotionListener;
0070: import java.awt.image.BufferedImage;
0071: import java.io.IOException;
0072: import java.net.URL;
0073: import java.util.ArrayList;
0074: import java.util.Collections;
0075: import java.util.HashSet;
0076: import java.util.Iterator;
0077: import java.util.List;
0078: import java.util.Set;
0079: import java.util.Timer;
0080: import java.util.TimerTask;
0081: import javax.swing.AbstractAction;
0082: import javax.swing.Action;
0083: import javax.swing.DebugGraphics;
0084: import javax.swing.ImageIcon;
0085: import javax.swing.JCheckBoxMenuItem;
0086: import javax.swing.JComponent;
0087: import javax.swing.JMenu;
0088: import javax.swing.JPopupMenu;
0089: import javax.swing.Scrollable;
0090: import javax.swing.SwingConstants;
0091: import javax.swing.SwingUtilities;
0092: import javax.swing.ToolTipManager;
0093: import org.netbeans.modules.vmd.game.dialog.DuplicateTiledLayerDialog;
0094: import org.netbeans.modules.vmd.game.dialog.NewSimpleTiledLayerDialog;
0095: import org.netbeans.modules.vmd.game.model.AnimatedTile;
0096: import org.netbeans.modules.vmd.game.model.ImageResource;
0097: import org.netbeans.modules.vmd.game.model.Layer;
0098: import org.netbeans.modules.vmd.game.model.Position;
0099: import org.netbeans.modules.vmd.game.model.Tile;
0100: import org.netbeans.modules.vmd.game.model.TileDataFlavor;
0101: import org.netbeans.modules.vmd.game.model.TiledLayer;
0102: import org.netbeans.modules.vmd.game.model.TiledLayerListener;
0103: import org.netbeans.modules.vmd.game.view.ColorConstants;
0104: import org.openide.DialogDescriptor;
0105: import org.openide.DialogDisplayer;
0106: import org.openide.util.NbBundle;
0107:
0108: /**
0109: *
0110: * @author kherink
0111: */
0112: public class TiledLayerEditorComponent extends JComponent implements
0113: MouseListener, Scrollable, TiledLayerListener {
0114:
0115: public static final boolean DEBUG = false;
0116:
0117: public static final byte GRID_MODE_DOTS = 0;
0118: public static final byte GRID_MODE_LINES = 1;
0119: public static final byte GRID_MODE_NOGRID = 2;
0120:
0121: private static final Color GRID_COLOR = ColorConstants.COLOR_OUTLINE_PLAIN;
0122: private static final Color ANIMATED_TILE_GRID_COLOR = Color.CYAN;
0123: private static final Color HILITE_COLOR = new Color(0, 0, 255, 20);
0124:
0125: private static final int CELL_BORDER_WIDTH = 0;
0126: private static final int SELECTION_BORDER_WIDTH = 2;
0127:
0128: private byte gridMode = GRID_MODE_LINES;
0129: private int gridWidth = 1;
0130:
0131: private TiledLayer tiledLayer;
0132:
0133: private int paintTileIndex = 0;
0134: private Color currentSelectedColor = Color.getHSBColor(0.0f, 1.0f,
0135: 0.0f);
0136:
0137: private int cellWidth;
0138: private int cellHeight;
0139:
0140: private Position cellHiLited;
0141: private Set<Position> cellsSelected = Collections
0142: .synchronizedSet(new HashSet<Position>());
0143:
0144: private Timer timer;
0145:
0146: RulerHorizontal rulerHorizontal;
0147: RulerVertical rulerVertical;
0148:
0149: public static final int EDIT_MODE_PAINT = 0;
0150: public static final int EDIT_MODE_SELECT = 1;
0151: public static final String PAINT_CURSOR_NAME = "CUSTOM_PAINT_CURSOR"; // NOI18N
0152:
0153: private int editMode;
0154:
0155: private static Cursor paintCursor;
0156: private static Cursor selectionCursor;
0157:
0158: static {
0159: //create custom cursors
0160: URL cursorUrl = TiledLayerEditorComponent.class
0161: .getResource("res/drawing_mode_mouse_16.png"); // NOI18N
0162: ImageIcon cursorIcon = new ImageIcon(cursorUrl);
0163: Image cursor;
0164: Dimension d = Toolkit.getDefaultToolkit().getBestCursorSize(
0165: cursorIcon.getIconWidth(), cursorIcon.getIconHeight());
0166: if (DEBUG)
0167: System.out.println("Best Cursor Size: " + d); // NOI18N
0168: if (DEBUG)
0169: System.out.println("Our Cursor Size: "
0170: + cursorIcon.getIconWidth() + " x "
0171: + cursorIcon.getIconHeight()); // NOI18N
0172: //if required cursor size is larger than the image we have then create a new buffimg of the required size and
0173: //draw our smaller cursor in the top-left corner to avoid auto-scaling
0174: if (d.width > cursorIcon.getIconWidth()
0175: && d.height > cursorIcon.getIconHeight()) {
0176: cursor = new BufferedImage(d.width, d.height,
0177: BufferedImage.TYPE_INT_ARGB);
0178: cursor.getGraphics().drawImage(cursorIcon.getImage(), 0, 0,
0179: null);
0180: } else {
0181: cursor = cursorIcon.getImage();
0182: }
0183: paintCursor = Toolkit.getDefaultToolkit().createCustomCursor(
0184: cursor, new Point(7, 7), PAINT_CURSOR_NAME);
0185:
0186: cursorUrl = TiledLayerEditorComponent.class
0187: .getResource("res/select_mode_mouse_16.png"); // NOI18N
0188: cursorIcon = new ImageIcon(cursorUrl);
0189: selectionCursor = Cursor.getDefaultCursor();
0190: }
0191:
0192: /** Creates a new instance of EditorComponent */
0193: public TiledLayerEditorComponent(TiledLayer tiledLayer) {
0194: this .setTiledLayer(tiledLayer);
0195: this .tiledLayer.addTiledLayerListener(this );
0196: this .addMouseListener(this );
0197: this .addMouseMotionListener(new PaintMotionListener());
0198: this .setAutoscrolls(true);
0199: this .timer = new Timer();
0200: this .timer.schedule(new HiliteAnimator(), 0, 100);
0201: ToolTipManager.sharedInstance().registerComponent(this );
0202: //DnD
0203: DropTarget dropTarget = new DropTarget(this ,
0204: new TiledLayerDropTargetListener());
0205: dropTarget.setActive(true);
0206: this .setDropTarget(dropTarget);
0207:
0208: this .rulerHorizontal = new RulerHorizontal();
0209: this .rulerVertical = new RulerVertical();
0210:
0211: this .setEditMode(EDIT_MODE_PAINT);
0212:
0213: // vlv: print
0214: putClientProperty(java.awt.print.Printable.class, ""); // NOI18N
0215: }
0216:
0217: public Dimension getMaximumSize() {
0218: return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
0219: }
0220:
0221: public void setGridMode(byte gridMode) {
0222: this .gridMode = gridMode;
0223: if (this .gridMode == GRID_MODE_NOGRID) {
0224: this .gridWidth = 0;
0225: } else {
0226: this .gridWidth = 1;
0227: }
0228: }
0229:
0230: public String getToolTipText(MouseEvent event) {
0231: Position cell = this .getCellAtPoint(event.getPoint());
0232: int index = this .tiledLayer.getTileIndexAt(cell);
0233: if (index < Tile.EMPTY_TILE_INDEX) {
0234: AnimatedTile tile = (AnimatedTile) this .tiledLayer
0235: .getTileAt(cell);
0236: return NbBundle.getMessage(TiledLayerEditorComponent.class,
0237: "TiledLayerEditorComponent.animTile.tooltip",
0238: new Object[] { tile.getName(), cell.getRow(),
0239: cell.getCol() });
0240: //return tile.getName() + " [" + cell.getRow() + "," + cell.getCol() + "]";
0241: }
0242: return NbBundle.getMessage(TiledLayerEditorComponent.class,
0243: "TiledLayerEditorComponent.tile.tooltip", new Object[] {
0244: index, cell.getRow(), cell.getCol() });
0245: //return "Index: " + index + " [" + cell.getRow() + "," + cell.getCol() + "]";
0246: }
0247:
0248: public Dimension getPreferredSize() {
0249: int width = this .gridWidth + (this .cellWidth + this .gridWidth)
0250: * this .tiledLayer.getColumnCount();
0251: int height = this .gridWidth
0252: + (this .cellHeight + this .gridWidth)
0253: * this .tiledLayer.getRowCount();
0254: return new Dimension(width, height);
0255: }
0256:
0257: public void setTiledLayer(TiledLayer tiledLayer) {
0258: this .tiledLayer = tiledLayer;
0259: this .cellWidth = this .tiledLayer.getTileWidth()
0260: + (CELL_BORDER_WIDTH * 2);
0261: this .cellHeight = this .tiledLayer.getTileHeight()
0262: + (CELL_BORDER_WIDTH * 2);
0263: }
0264:
0265: public void paintComponent(Graphics g) {
0266: if (DEBUG)
0267: System.out.println("EditorComponent clip : "
0268: + g.getClipBounds()); // NOI18N
0269: if (g instanceof DebugGraphics)
0270: return;
0271: Graphics2D g2d = (Graphics2D) g;
0272: if (gridMode == GRID_MODE_DOTS)
0273: this .paintGridDots(g2d);
0274: else
0275: this .paintGridLines(g2d);
0276: this .paintCells(g2d);
0277:
0278: if (this .cellHiLited != null) {
0279: this .paintGridHiLite((Graphics2D) g, cellHiLited,
0280: ColorConstants.COLOR_OUTLINE_SELECTED);
0281: }
0282: }
0283:
0284: //paints GRID as dots
0285: private void paintGridDots(Graphics2D g) {
0286: //Rectangle rect = g.getClipBounds();
0287: g.setColor(Color.BLACK);
0288: for (int horizontal = 0; horizontal < this .getHeight(); horizontal += (this .cellHeight + this .gridWidth)) {
0289: //g.fillRect(0, horizontal, this.getWidth(), this.gridWidth);
0290: for (int vertical = 0; vertical < this .getWidth(); vertical += (cellWidth + this .gridWidth)) {
0291: //g.fillRect(vertical, 0, this.gridWidth, this.getHeight());
0292: g.fillRect(vertical, horizontal, 1, 1);
0293: }
0294: }
0295: }
0296:
0297: //paints GRID as lines
0298: private void paintGridLines(Graphics2D g) {
0299: //Rectangle rect = g.getClipBounds();
0300: g.setColor(GRID_COLOR);
0301: for (int horizontal = 0; horizontal < this .getHeight(); horizontal += (this .cellHeight + this .gridWidth)) {
0302: //g.drawLine(0, horizontal, this.getWidth(), horizontal);
0303: g.fillRect(0, horizontal, this .getWidth(), this .gridWidth);
0304: }
0305: for (int vertical = 0; vertical < this .getWidth(); vertical += (cellWidth + this .gridWidth)) {
0306: //g.drawLine(vertical, 0, vertical, this.getHeight());
0307: g.fillRect(vertical, 0, this .gridWidth, this .getHeight());
0308: }
0309: }
0310:
0311: /**
0312: * Returns four integers [topLeftRow, topLeftColumn, bottomRightRow, bottomRightColumn] these
0313: * signify the currently visible grid area.
0314: */
0315: private int[] getVisibleCellBounds() {
0316: int[] ret = new int[4];
0317: Rectangle rect = this .getVisibleRect();
0318: Position topLeft = this .getCellAtPoint(rect.getLocation());
0319: Position bottomRight = this .getCellAtCoordinates(rect
0320: .getLocation().x
0321: + rect.width, rect.getLocation().y + rect.height);
0322: ret[0] = topLeft.getRow();
0323: ret[1] = topLeft.getCol();
0324: ret[2] = bottomRight.getRow();
0325: ret[3] = bottomRight.getCol();
0326: return ret;
0327: }
0328:
0329: void paintCells(Graphics2D g) {
0330: Rectangle rect = g.getClipBounds();
0331: if (DEBUG)
0332: System.out.println("Paint cell: " + rect); // NOI18N
0333: Position topLeft = this .getCellAtPoint(rect.getLocation());
0334: Position bottomRight = this .getCellAtCoordinates(rect
0335: .getLocation().x
0336: + rect.width, rect.getLocation().y + rect.height);
0337: //if (DEBUG) System.out.println("topLeft: " + topLeft + ", bottomRight: " + bottomRight);
0338: //rows
0339: for (int row = topLeft.getRow(); row <= bottomRight.getRow(); row++) {
0340: //cols
0341: for (int col = topLeft.getCol(); col <= bottomRight
0342: .getCol(); col++) {
0343: Position cell = new Position(row, col);
0344: //if (DEBUG) System.out.println("Looking at: " + cell + " compared to " + this.cellHiLited);
0345: this .paintCellContents(g, cell);
0346:
0347: //paint selected cells
0348: if (this .currentSelectedColor != null
0349: && (this .cellsSelected.contains(cell))) {
0350: this .paintCellSelection(g, cell,
0351: this .currentSelectedColor);
0352: }
0353:
0354: //hi-lite animated tiles
0355: if (this .tiledLayer.getTileAt(cell).getIndex() < 0) {
0356: //if (DEBUG) System.out.println("animated grid");
0357: this .paintGridHiLite(g, cell,
0358: ANIMATED_TILE_GRID_COLOR);
0359: }
0360: }
0361: }
0362: }
0363:
0364: private void paintCellContents(Graphics2D g, Position cell) {
0365: Tile tile = this .tiledLayer.getTileAt(cell.getRow(), cell
0366: .getCol());
0367: Rectangle rect = this .getCellArea(cell);
0368: int x = rect.x + CELL_BORDER_WIDTH;
0369: int y = rect.y + CELL_BORDER_WIDTH;
0370: tile.paint(g, x, y);
0371: }
0372:
0373: private void paintCellSelection(Graphics2D g, Position cell,
0374: Color color) {
0375: //if (DEBUG) System.out.println("paintCellSelection: " + cell.toString());
0376: Rectangle rect = this .getCellArea(cell);
0377: g.setColor(color);
0378: g.fillRect(rect.x, rect.y, rect.width, SELECTION_BORDER_WIDTH);
0379: g.fillRect(rect.x, rect.y, SELECTION_BORDER_WIDTH, rect.height
0380: - (this .gridWidth * 2));
0381: g.fillRect(rect.x + (rect.width - SELECTION_BORDER_WIDTH),
0382: rect.y, SELECTION_BORDER_WIDTH, rect.height);
0383: g.fillRect(rect.x, rect.y
0384: + (rect.height - SELECTION_BORDER_WIDTH), rect.width,
0385: SELECTION_BORDER_WIDTH);
0386: }
0387:
0388: private void paintGridHiLite(Graphics2D g, Position cell,
0389: Color color) {
0390: //if (DEBUG) System.out.println("paintGridHiLite: " + cell.toString());
0391: Rectangle rect = this .getCellArea(cell);
0392: g.setColor(color);
0393: g.fillRect(rect.x, rect.y, rect.width, this .gridWidth);
0394: g.fillRect(rect.x, rect.y, this .gridWidth, rect.height);
0395: g.fillRect(rect.x + (rect.width - this .gridWidth), rect.y,
0396: this .gridWidth, rect.height);
0397: g.fillRect(rect.x, rect.y + (rect.height - this .gridWidth),
0398: rect.width, this .gridWidth);
0399: }
0400:
0401: TiledLayer getTiledLayer() {
0402: return this .tiledLayer;
0403: }
0404:
0405: private Position getCellAtPoint(Point p) {
0406: return this .getCellAtCoordinates(p.x, p.y);
0407: }
0408:
0409: private Position getCellAtCoordinates(int x, int y) {
0410: int row = (y - this .gridWidth)
0411: / (this .cellHeight + this .gridWidth);
0412: int col = (x - this .gridWidth)
0413: / (this .cellWidth + this .gridWidth);
0414: if (x < 0) {
0415: col--;
0416: }
0417: if (y < 0) {
0418: row--;
0419: }
0420: //if (DEBUG) System.out.println("row = " + row + " col = " + col);
0421: return new Position(row, col);
0422: }
0423:
0424: private Rectangle getCellArea(Position cell) {
0425: return this .getCellArea(cell.getRow(), cell.getCol());
0426: }
0427:
0428: private Rectangle getCellArea(int row, int col) {
0429: Rectangle cellArea = new Rectangle(
0430: ((this .cellWidth + this .gridWidth) * col)
0431: + this .gridWidth,
0432: ((this .cellHeight + this .gridWidth) * row)
0433: + this .gridWidth, this .cellWidth,
0434: this .cellHeight);
0435: return cellArea;
0436: }
0437:
0438: void setPaintTileIndex(int index) {
0439: this .paintTileIndex = index;
0440: }
0441:
0442: private void selectByIndex(int index) {
0443: synchronized (this .cellsSelected) {
0444: for (int r = 0; r < this .tiledLayer.getRowCount(); r++) {
0445: for (int c = 0; c < this .tiledLayer.getColumnCount(); c++) {
0446: if (this .tiledLayer.getTileAt(r, c).getIndex() == index) {
0447: this .cellsSelected.add(new Position(r, c));
0448: }
0449: }
0450: }
0451: }
0452: }
0453:
0454: private void selectAll() {
0455: synchronized (this .cellsSelected) {
0456: for (int r = 0; r < this .tiledLayer.getRowCount(); r++) {
0457: for (int c = 0; c < this .tiledLayer.getColumnCount(); c++) {
0458: this .cellsSelected.add(new Position(r, c));
0459: }
0460: }
0461: }
0462: }
0463:
0464: private void invertSelection() {
0465: synchronized (this .cellsSelected) {
0466: for (int r = 0; r < this .tiledLayer.getRowCount(); r++) {
0467: for (int c = 0; c < this .tiledLayer.getColumnCount(); c++) {
0468: Position p = new Position(r, c);
0469: if (this .cellsSelected.contains(p)) {
0470: this .cellsSelected.remove(p);
0471: } else {
0472: this .cellsSelected.add(p);
0473: }
0474: }
0475: }
0476: }
0477: this .repaint();
0478: }
0479:
0480: //----- mouse handling ------
0481:
0482: public void setEditMode(int editMode) {
0483: this .editMode = editMode;
0484: this .setCursor(editMode == EDIT_MODE_PAINT ? paintCursor
0485: : selectionCursor);
0486: }
0487:
0488: private boolean isPaintMode() {
0489: return this .editMode == EDIT_MODE_PAINT;
0490: }
0491:
0492: private boolean isSelectMode() {
0493: return this .editMode == EDIT_MODE_SELECT;
0494: }
0495:
0496: //MouseListener
0497: public void mouseClicked(MouseEvent e) {
0498: this .handleMouseClicked(e);
0499: }
0500:
0501: //MouseListener
0502: public void mousePressed(MouseEvent e) {
0503: if (e.isPopupTrigger()) {
0504: this .doPopUp(e);
0505: } else {
0506: this .handleMousePressed(e);
0507: }
0508: }
0509:
0510: //MouseListener
0511: public void mouseReleased(MouseEvent e) {
0512: this .firstDraggedCell = null;
0513: this .lastDraggedCell = null;
0514: if (e.isPopupTrigger()) {
0515: this .doPopUp(e);
0516: }
0517: }
0518:
0519: //MouseListener
0520: public void mouseEntered(MouseEvent e) {
0521: }
0522:
0523: //MouseListener
0524: public void mouseExited(MouseEvent e) {
0525: Position oldHilited = this .cellHiLited;
0526: this .cellHiLited = null;
0527: if (oldHilited != null)
0528: this .repaint(this .getCellArea(oldHilited));
0529: }
0530:
0531: private Position firstDraggedCell;
0532: private Position lastDraggedCell;
0533:
0534: private void handleMouseClicked(MouseEvent e) {
0535: this .firstDraggedCell = null;
0536: this .lastDraggedCell = null;
0537:
0538: Position cell = this .getCellAtCoordinates(e.getX(), e.getY());
0539: if (SwingUtilities.isRightMouseButton(e)) {
0540: return;
0541: }
0542:
0543: if (isSelectMode()) {
0544: if (e.getClickCount() >= 2
0545: && !SwingUtilities.isRightMouseButton(e)) {
0546: this .selectByIndex(this .tiledLayer.getTileAt(
0547: cell.getRow(), cell.getCol()).getIndex());
0548: }
0549: this .tiledLayer.getGameDesign().getMainView()
0550: .requestPreview(
0551: this .tiledLayer.getTileAt(cell.getRow(),
0552: cell.getCol()));
0553: } else if (isPaintMode()) {
0554: //do nothing, painting happens on mouse pressed
0555: }
0556: this .repaint(getCellArea(cell));
0557: }
0558:
0559: private void handleMousePressed(MouseEvent e) {
0560: if (!SwingUtilities.isLeftMouseButton(e)) {
0561: return;
0562: }
0563:
0564: Position cell = this .getCellAtCoordinates(e.getX(), e.getY());
0565: this .firstDraggedCell = cell;
0566: this .lastDraggedCell = cell;
0567:
0568: if (this .isSelectMode()) {
0569: synchronized (this .cellsSelected) {
0570: if (e.isControlDown()) {
0571: //ctrl-left_press toogle a single cell without affecting other selection
0572: if (!this .cellsSelected.remove(cell)) {
0573: this .cellsSelected.add(cell);
0574: }
0575: } else if (e.isMetaDown() || e.isShiftDown()) {
0576: this .cellsSelected.add(cell);
0577: } else {
0578: this .cellsSelected.clear();
0579: this .cellsSelected.add(cell);
0580: }
0581: }
0582: } else if (isPaintMode()) {
0583: this .tiledLayer.setTileAt(this .paintTileIndex, cell
0584: .getRow(), cell.getCol());
0585: Set oldSelected = this .cellsSelected;
0586: this .cellsSelected = new HashSet<Position>();
0587: for (Iterator it = oldSelected.iterator(); it.hasNext();) {
0588: Position oldSelCel = (Position) it.next();
0589: this .repaint(getCellArea(oldSelCel));
0590: }
0591: }
0592:
0593: this .repaint();
0594: this .tiledLayer.getGameDesign().getMainView()
0595: .requestPreview(
0596: this .tiledLayer.getTileAt(cell.getRow(), cell
0597: .getCol()));
0598: }
0599:
0600: //MouseMotionListener
0601: private class PaintMotionListener extends MouseMotionAdapter {
0602:
0603: public void mouseDragged(MouseEvent e) {
0604: Point point = e.getPoint();
0605: Position cell = TiledLayerEditorComponent.this
0606: .getCellAtPoint(point);
0607:
0608: if (TiledLayerEditorComponent.this .isSelectMode()) {
0609: if (cell.equals(lastDraggedCell)) {
0610: return;
0611: }
0612: if (DEBUG)
0613: System.out.println("Drag from " + lastDraggedCell
0614: + " to " + cell); // NOI18N
0615:
0616: synchronized (TiledLayerEditorComponent.this .cellsSelected) {
0617: if (false) {
0618: TiledLayerEditorComponent.this .cellsSelected
0619: .remove(cell);
0620: }
0621: if (false) {
0622: int rowStep = firstDraggedCell.getRow() <= cell
0623: .getRow() ? 1 : -1;
0624: if (DEBUG)
0625: System.out.println("row step : " + rowStep); // NOI18N
0626: int colStep = firstDraggedCell.getCol() <= cell
0627: .getCol() ? 1 : -1;
0628: if (DEBUG)
0629: System.out.println("col step : " + colStep); // NOI18N
0630:
0631: //if drag change in colls
0632: if (cell.getCol() != lastDraggedCell.getCol()) {
0633:
0634: int dcOld = Math.abs(lastDraggedCell
0635: .getCol()
0636: - firstDraggedCell.getCol());
0637: int dcNew = Math.abs(cell.getCol()
0638: - firstDraggedCell.getCol());
0639: if (DEBUG)
0640: System.out.println("COL dcOld: "
0641: + dcOld + ", dcNew: " + dcNew); // NOI18N
0642:
0643: Set<Position> deltaNewSet = new HashSet<Position>();
0644: for (int c = lastDraggedCell.getCol(); c != cell
0645: .getCol(); c += colStep) {
0646: if (DEBUG)
0647: System.out.print("c = " + c);
0648: for (int r = firstDraggedCell.getRow(); r != cell
0649: .getRow(); r += rowStep) {
0650: if (DEBUG)
0651: System.out.println(" r = " + r);
0652: Position pos = new Position(r, c);
0653: if (DEBUG)
0654: System.out
0655: .println("\tadd to delta "
0656: + pos); // NOI18N
0657: deltaNewSet.add(pos);
0658: }
0659: }
0660:
0661: //if shrinking selection - remove the deltaSet
0662: if (dcOld > dcNew) {
0663: if (DEBUG)
0664: System.out.println("remove delta"); // NOI18N
0665: cellsSelected.removeAll(deltaNewSet);
0666: }
0667: //else growing selection - add the deltaSet
0668: else {
0669: if (DEBUG)
0670: System.out.println("add delta"); // NOI18N
0671: cellsSelected.addAll(deltaNewSet);
0672: }
0673: }
0674:
0675: //change in rows
0676: if (cell.getRow() != lastDraggedCell.getRow()) {
0677: int dcOld = Math.abs(lastDraggedCell
0678: .getRow()
0679: - firstDraggedCell.getRow());
0680: int dcNew = Math.abs(cell.getRow()
0681: - firstDraggedCell.getRow());
0682: if (DEBUG)
0683: System.out.println("ROW dcOld: "
0684: + dcOld + ", dcNew: " + dcNew); // NOI18N
0685:
0686: Set<Position> deltaSet = new HashSet<Position>();
0687: for (int r = lastDraggedCell.getRow(); r != cell
0688: .getRow(); r -= rowStep) {
0689: for (int c = lastDraggedCell.getCol(); c != cell
0690: .getCol(); c -= colStep) {
0691: Position pos = new Position(r, c);
0692: if (DEBUG)
0693: System.out
0694: .println("\tadd to delta "
0695: + pos); // NOI18N
0696: deltaSet.add(pos);
0697: }
0698: }
0699:
0700: //if shrinking selection - remove the deltaSet
0701: if (dcOld > dcNew) {
0702: if (DEBUG)
0703: System.out.println("remove delta"); // NOI18N
0704: cellsSelected.removeAll(deltaSet);
0705: }
0706: //else growing selection - add the deltaSet
0707: else {
0708: if (DEBUG)
0709: System.out.println("add delta"); // NOI18N
0710: cellsSelected.addAll(deltaSet);
0711: }
0712: }
0713:
0714: TiledLayerEditorComponent.this .lastDraggedCell = cell;
0715: } else {
0716: TiledLayerEditorComponent.this .cellsSelected
0717: .add(cell);
0718: }
0719: }
0720: } else if (TiledLayerEditorComponent.this .isPaintMode()) {
0721: int tileIndex = TiledLayerEditorComponent.this .paintTileIndex;
0722: //if we are on the same tile and trying to paint the same index then we aren't really changing anything :)
0723: if (cell.equals(lastDraggedCell)
0724: && (tileIndex == TiledLayerEditorComponent.this .tiledLayer
0725: .getTileAt(cell.getRow(), cell.getCol())
0726: .getIndex()))
0727: return;
0728: if (lastDraggedCell != null)
0729: TiledLayerEditorComponent.this
0730: .repaint(TiledLayerEditorComponent.this
0731: .getCellArea(lastDraggedCell));
0732: TiledLayerEditorComponent.this .cellHiLited = cell;
0733: //if (DEBUG) System.out.println("tile index = " + tileIndex);
0734: TiledLayerEditorComponent.this .tiledLayer.setTileAt(
0735: tileIndex, cell.getRow(), cell.getCol());
0736: }
0737:
0738: TiledLayerEditorComponent.this
0739: .repaint(TiledLayerEditorComponent.this
0740: .getCellArea(cell));
0741: TiledLayerEditorComponent.this .lastDraggedCell = cell;
0742: //The user is dragging us, so scroll!
0743: Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
0744: scrollRectToVisible(r);
0745: }
0746:
0747: public void mouseMoved(MouseEvent e) {
0748: TiledLayerEditorComponent.this .updateHiLite(e.getPoint());
0749: }
0750: }
0751:
0752: private void doPopUp(MouseEvent e) {
0753: Position position = this .getCellAtPoint(e.getPoint());
0754:
0755: DuplicateTiledLayerAction dtl = new DuplicateTiledLayerAction();
0756: CreateFromSelectionAction cfs = new CreateFromSelectionAction();
0757: EraseSelectionAction es = new EraseSelectionAction();
0758: if (TiledLayerEditorComponent.this .cellsSelected.size() < 2) {
0759: cfs.setEnabled(false);
0760: }
0761:
0762: SelectRowAction sr = new SelectRowAction();
0763: sr.putValue(SelectRowAction.PROP_POSITION, position);
0764:
0765: SelectColumnAction sc = new SelectColumnAction();
0766: sc.putValue(SelectColumnAction.PROP_POSITION, position);
0767:
0768: SelectByIndexAction sbi = new SelectByIndexAction();
0769: sbi.putValue(SelectByIndexAction.PROP_POSITION, position);
0770:
0771: SelectAllAction sa = new SelectAllAction();
0772:
0773: InvertSelectionAction is = new InvertSelectionAction();
0774:
0775: PrependRowAction pr = new PrependRowAction();
0776: pr.putValue(PrependRowAction.PROP_POSITION, position);
0777:
0778: AppendRowAction ar = new AppendRowAction();
0779: ar.putValue(AppendRowAction.PROP_POSITION, position);
0780:
0781: PrependColumnAction pc = new PrependColumnAction();
0782: pc.putValue(PrependColumnAction.PROP_POSITION, position);
0783:
0784: AppendColumnAction ac = new AppendColumnAction();
0785: ac.putValue(AppendColumnAction.PROP_POSITION, position);
0786:
0787: DeleteRowAction dr = new DeleteRowAction();
0788: dr.putValue(DeleteRowAction.PROP_POSITION, position);
0789:
0790: DeleteColumnAction dc = new DeleteColumnAction();
0791: dc.putValue(DeleteColumnAction.PROP_POSITION, position);
0792:
0793: TrimToSizeAction tts = new TrimToSizeAction();
0794:
0795: JCheckBoxMenuItem itemPaint = new JCheckBoxMenuItem(NbBundle
0796: .getMessage(TiledLayerEditorComponent.class,
0797: "TiledLayerEditorComponent.menuModePaint.txt"),
0798: this .editMode == EDIT_MODE_PAINT);
0799: itemPaint
0800: .addItemListener(new EditModeListener(EDIT_MODE_PAINT));
0801:
0802: JCheckBoxMenuItem itemSelect = new JCheckBoxMenuItem(
0803: NbBundle.getMessage(TiledLayerEditorComponent.class,
0804: "TiledLayerEditorComponent.menuModeSelect.txt"),
0805: this .editMode == EDIT_MODE_SELECT);
0806: itemSelect.addItemListener(new EditModeListener(
0807: EDIT_MODE_SELECT));
0808:
0809: JPopupMenu menu = new JPopupMenu();
0810:
0811: menu.add(dtl);
0812: List<Action> actions = this .tiledLayer.getActions();
0813: for (Action action : actions) {
0814: //don't wanna add edit action since we are already editing :)
0815: if (action instanceof Layer.EditLayerAction)
0816: continue;
0817: menu.add(action);
0818: }
0819: menu.addSeparator();
0820: menu.add(cfs);
0821: menu.add(es);
0822: JMenu selecttionSubMenu = new JMenu(NbBundle.getMessage(
0823: TiledLayerEditorComponent.class,
0824: "TiledLayerEditorComponent.menuSelect.txt"));
0825: selecttionSubMenu.add(selecttionSubMenu);
0826: selecttionSubMenu.add(sr);
0827: selecttionSubMenu.add(sc);
0828: selecttionSubMenu.add(sbi);
0829: selecttionSubMenu.add(sa);
0830: selecttionSubMenu.add(is);
0831: menu.add(selecttionSubMenu);
0832: menu.addSeparator();
0833: menu.add(pr);
0834: menu.add(ar);
0835: menu.add(pc);
0836: menu.add(ac);
0837: menu.addSeparator();
0838: menu.add(dr);
0839: menu.add(dc);
0840: menu.addSeparator();
0841: menu.add(tts);
0842:
0843: menu.show(this , e.getX(), e.getY());
0844: }
0845:
0846: private class EditModeListener implements ItemListener {
0847: private int mode;
0848:
0849: public EditModeListener(int mode) {
0850: this .mode = mode;
0851: }
0852:
0853: public void itemStateChanged(ItemEvent e) {
0854: if (DEBUG)
0855: System.out.println("setting edit mode"); // NOI18N
0856: TiledLayerEditorComponent.this .setEditMode(this .mode);
0857: }
0858: }
0859:
0860: // public class CreateTiledLayerAction extends AbstractAction {
0861: // {
0862: // this.putValue(NAME, "New Tiled Layer");
0863: // }
0864: //
0865: // public void actionPerformed(ActionEvent e) {
0866: // TiledLayerDialog nld = new TiledLayerDialog(TiledLayerEditorComponent.this.tiledLayer.getGameDesign());
0867: // DialogDescriptor dd = new DialogDescriptor(nld, "Create new TiledLayer");
0868: // dd.setButtonListener(nld);
0869: // dd.setValid(false);
0870: // nld.setDialogDescriptor(dd);
0871: // Dialog d = DialogDisplayer.getDefault().createDialog(dd);
0872: // d.setVisible(true);
0873: // }
0874: // }
0875:
0876: public class DuplicateTiledLayerAction extends AbstractAction {
0877: {
0878: this
0879: .putValue(
0880: NAME,
0881: NbBundle
0882: .getMessage(
0883: TiledLayerEditorComponent.class,
0884: "TiledLayerEditorComponent.actionDuplicateTiledLayer.txt"));
0885: }
0886:
0887: public void actionPerformed(ActionEvent e) {
0888: DuplicateTiledLayerDialog dialog = new DuplicateTiledLayerDialog(
0889: TiledLayerEditorComponent.this .tiledLayer);
0890: DialogDescriptor dd = new DialogDescriptor(
0891: dialog,
0892: NbBundle
0893: .getMessage(
0894: TiledLayerEditorComponent.class,
0895: "TiledLayerEditorComponent.actionDuplicateTiledLayer.txt"));
0896: dd.setButtonListener(dialog);
0897: dd.setValid(false);
0898: dialog.setDialogDescriptor(dd);
0899: Dialog d = DialogDisplayer.getDefault().createDialog(dd);
0900: d.setVisible(true);
0901: }
0902: }
0903:
0904: public class TrimToSizeAction extends AbstractAction {
0905: {
0906: this .putValue(NAME, NbBundle.getMessage(
0907: TiledLayerEditorComponent.class,
0908: "TiledLayerEditorComponent.actionTrim.txt"));
0909: }
0910:
0911: public void actionPerformed(ActionEvent e) {
0912: TiledLayerEditorComponent.this .tiledLayer.trimToSize();
0913: }
0914: }
0915:
0916: public class CreateFromSelectionAction extends AbstractAction {
0917: {
0918: this
0919: .putValue(
0920: NAME,
0921: NbBundle
0922: .getMessage(
0923: TiledLayerEditorComponent.class,
0924: "TiledLayerEditorComponent.actionNewFromSelection.txt"));
0925: }
0926:
0927: public void actionPerformed(ActionEvent e) {
0928: int left = Integer.MAX_VALUE;
0929: int right = Integer.MIN_VALUE;
0930: int top = Integer.MAX_VALUE;
0931: int bottom = Integer.MIN_VALUE;
0932: int[][] grid;
0933: synchronized (TiledLayerEditorComponent.this .cellsSelected) {
0934: if (TiledLayerEditorComponent.this .cellsSelected.size() < 2)
0935: return;
0936: Set<Position> cells = TiledLayerEditorComponent.this .cellsSelected;
0937: //first find the grid size that can hold all the selected cells
0938: for (Position position : cells) {
0939: //find left boundry
0940: left = Math.min(left, position.getCol());
0941: //find right boundry
0942: right = Math.max(right, position.getCol());
0943: //find top boundry
0944: top = Math.min(top, position.getRow());
0945: //find bottom boundry
0946: bottom = Math.max(bottom, position.getRow());
0947: }
0948: //then fill the grid with selected cells
0949: grid = new int[(bottom - top) + 1][(right - left) + 1];
0950: for (Position position : cells) {
0951: grid[position.getRow() - top][position.getCol()
0952: - left] = TiledLayerEditorComponent.this .tiledLayer
0953: .getTileIndexAt(position);
0954: }
0955: }
0956:
0957: NewSimpleTiledLayerDialog dialog = new NewSimpleTiledLayerDialog(
0958: TiledLayerEditorComponent.this .tiledLayer
0959: .getImageResource(), grid,
0960: TiledLayerEditorComponent.this .tiledLayer
0961: .getTileWidth(),
0962: TiledLayerEditorComponent.this .tiledLayer
0963: .getTileHeight());
0964: DialogDescriptor dd = new DialogDescriptor(
0965: dialog,
0966: NbBundle
0967: .getMessage(
0968: TiledLayerEditorComponent.class,
0969: "TiledLayerEditorComponent.actionNewFromSelection.txt"));
0970: dd.setButtonListener(dialog);
0971: dd.setValid(false);
0972: dialog.setDialogDescriptor(dd);
0973: Dialog d = DialogDisplayer.getDefault().createDialog(dd);
0974: d.setVisible(true);
0975: }
0976: }
0977:
0978: public class EraseSelectionAction extends AbstractAction {
0979: {
0980: this
0981: .putValue(
0982: NAME,
0983: NbBundle
0984: .getMessage(
0985: TiledLayerEditorComponent.class,
0986: "TiledLayerEditorComponent.actionEraseSelection.txt"));
0987: }
0988:
0989: public void actionPerformed(ActionEvent e) {
0990: TiledLayerEditorComponent.this .tiledLayer
0991: .setTileAtPositions(
0992: Tile.EMPTY_TILE_INDEX,
0993: TiledLayerEditorComponent.this .cellsSelected);
0994: }
0995: }
0996:
0997: public class DeleteColumnAction extends AbstractAction {
0998: public static final String PROP_POSITION = "PROP_POSITION"; // NOI18N
0999: {
1000: this .putValue(NAME, NbBundle.getMessage(
1001: TiledLayerEditorComponent.class,
1002: "TiledLayerEditorComponent.actionDeleteCol.txt"));
1003: }
1004:
1005: public void actionPerformed(ActionEvent e) {
1006: Position p = ((Position) this .getValue(PROP_POSITION));
1007: TiledLayerEditorComponent.this .tiledLayer.deleteColumns(p
1008: .getCol(), 1);
1009: }
1010: }
1011:
1012: public class DeleteRowAction extends AbstractAction {
1013: public static final String PROP_POSITION = "PROP_POSITION"; // NOI18N
1014: {
1015: this .putValue(NAME, NbBundle.getMessage(
1016: TiledLayerEditorComponent.class,
1017: "TiledLayerEditorComponent.actionDeleteRow.txt"));
1018: }
1019:
1020: public void actionPerformed(ActionEvent e) {
1021: Position p = ((Position) this .getValue(PROP_POSITION));
1022: TiledLayerEditorComponent.this .tiledLayer.deleteRows(p
1023: .getRow(), 1);
1024: }
1025: }
1026:
1027: public class SelectColumnAction extends AbstractAction {
1028: public static final String PROP_POSITION = "PROP_POSITION"; // NOI18N
1029: {
1030: this .putValue(NAME, NbBundle.getMessage(
1031: TiledLayerEditorComponent.class,
1032: "TiledLayerEditorComponent.actionSelectCol.txt"));
1033: }
1034:
1035: public void actionPerformed(ActionEvent e) {
1036: Position p = ((Position) this .getValue(PROP_POSITION));
1037: TiledLayerEditorComponent.this .setColumnSelection(p
1038: .getCol(), true);
1039: }
1040: }
1041:
1042: public class SelectRowAction extends AbstractAction {
1043: public static final String PROP_POSITION = "PROP_POSITION"; // NOI18N
1044: {
1045: this .putValue(NAME, NbBundle.getMessage(
1046: TiledLayerEditorComponent.class,
1047: "TiledLayerEditorComponent.actionSelectRow.txt"));
1048: }
1049:
1050: public void actionPerformed(ActionEvent e) {
1051: Position p = ((Position) this .getValue(PROP_POSITION));
1052: TiledLayerEditorComponent.this .setRowSelection(p.getRow(),
1053: true);
1054: }
1055: }
1056:
1057: public class SelectByIndexAction extends AbstractAction {
1058: public static final String PROP_POSITION = "PROP_POSITION"; // NOI18N
1059: {
1060: this .putValue(NAME, NbBundle.getMessage(
1061: TiledLayerEditorComponent.class,
1062: "TiledLayerEditorComponent.actionSelectIndex.txt"));
1063: }
1064:
1065: public void actionPerformed(ActionEvent e) {
1066: Position p = ((Position) this .getValue(PROP_POSITION));
1067: TiledLayerEditorComponent.this
1068: .selectByIndex(TiledLayerEditorComponent.this .tiledLayer
1069: .getTileIndexAt(p));
1070: }
1071: }
1072:
1073: public class InvertSelectionAction extends AbstractAction {
1074: {
1075: this
1076: .putValue(
1077: NAME,
1078: NbBundle
1079: .getMessage(
1080: TiledLayerEditorComponent.class,
1081: "TiledLayerEditorComponent.actionInvertSelection.txt"));
1082: }
1083:
1084: public void actionPerformed(ActionEvent e) {
1085: TiledLayerEditorComponent.this .invertSelection();
1086: }
1087: }
1088:
1089: public class SelectAllAction extends AbstractAction {
1090: {
1091: this .putValue(NAME, NbBundle.getMessage(
1092: TiledLayerEditorComponent.class,
1093: "TiledLayerEditorComponent.actionSelectAll.txt"));
1094: }
1095:
1096: public void actionPerformed(ActionEvent e) {
1097: TiledLayerEditorComponent.this .selectAll();
1098: }
1099: }
1100:
1101: public class PrependRowAction extends AbstractAction {
1102: public static final String PROP_POSITION = "PROP_POSITION"; // NOI18N
1103: {
1104: this .putValue(NAME, NbBundle.getMessage(
1105: TiledLayerEditorComponent.class,
1106: "TiledLayerEditorComponent.actionPrependRow.txt"));
1107: }
1108:
1109: public void actionPerformed(ActionEvent e) {
1110: Position p = ((Position) this .getValue(PROP_POSITION));
1111: TiledLayerEditorComponent.this .tiledLayer.insertRows(p
1112: .getRow(), 1);
1113: }
1114: }
1115:
1116: public class AppendRowAction extends AbstractAction {
1117: public static final String PROP_POSITION = "PROP_POSITION"; // NOI18N
1118: {
1119: this .putValue(NAME, NbBundle.getMessage(
1120: TiledLayerEditorComponent.class,
1121: "TiledLayerEditorComponent.actionAppendRow.txt"));
1122: }
1123:
1124: public void actionPerformed(ActionEvent e) {
1125: Position p = ((Position) this .getValue(PROP_POSITION));
1126: TiledLayerEditorComponent.this .tiledLayer.insertRows(p
1127: .getRow() + 1, 1);
1128: }
1129: }
1130:
1131: public class PrependColumnAction extends AbstractAction {
1132: public static final String PROP_POSITION = "PROP_POSITION"; // NOI18N
1133: {
1134: this .putValue(NAME, NbBundle.getMessage(
1135: TiledLayerEditorComponent.class,
1136: "TiledLayerEditorComponent.actionPrependCol.txt"));
1137: }
1138:
1139: public void actionPerformed(ActionEvent e) {
1140: Position p = ((Position) this .getValue(PROP_POSITION));
1141: TiledLayerEditorComponent.this .tiledLayer.insertColumns(p
1142: .getCol(), 1);
1143: }
1144: }
1145:
1146: public class AppendColumnAction extends AbstractAction {
1147: public static final String PROP_POSITION = "PROP_POSITION"; // NOI18N
1148: {
1149: this .putValue(NAME, NbBundle.getMessage(
1150: TiledLayerEditorComponent.class,
1151: "TiledLayerEditorComponent.actionAppendCol.txt"));
1152: }
1153:
1154: public void actionPerformed(ActionEvent e) {
1155: Position p = ((Position) this .getValue(PROP_POSITION));
1156: TiledLayerEditorComponent.this .tiledLayer.insertColumns(p
1157: .getCol() + 1, 1);
1158: }
1159: }
1160:
1161: private boolean isRowSelected(int row) {
1162: int cols = this .tiledLayer.getColumnCount();
1163: for (int col = 0; col < cols; col++) {
1164: if (!cellsSelected.contains(new Position(row, col))) {
1165: return false;
1166: }
1167: }
1168: return true;
1169: }
1170:
1171: private void setRowSelection(int row, boolean selected) {
1172: synchronized (this .cellsSelected) {
1173: if (selected) {
1174: int cols = this .tiledLayer.getColumnCount();
1175: for (int i = 0; i < cols; i++) {
1176: this .cellsSelected.add(new Position(row, i));
1177: }
1178: } else {
1179: for (Iterator<Position> it = cellsSelected.iterator(); it
1180: .hasNext();) {
1181: Position position = it.next();
1182: if (position.getRow() == row) {
1183: it.remove();
1184: }
1185: }
1186: }
1187: }
1188: //TODO : repaint the row only
1189: this .repaint();
1190: }
1191:
1192: private boolean isColumnsSelected(int col) {
1193: int rows = this .tiledLayer.getRowCount();
1194: for (int row = 0; row < rows; row++) {
1195: if (!this .cellsSelected.contains(new Position(row, col))) {
1196: return false;
1197: }
1198: }
1199: return true;
1200: }
1201:
1202: private void setColumnSelection(int col, boolean selected) {
1203: synchronized (this .cellsSelected) {
1204: if (selected) {
1205: int rows = this .tiledLayer.getRowCount();
1206: for (int row = 0; row < rows; row++) {
1207: this .cellsSelected.add(new Position(row, col));
1208: }
1209: } else {
1210: for (Iterator<Position> it = cellsSelected.iterator(); it
1211: .hasNext();) {
1212: Position position = it.next();
1213: if (position.getCol() == col) {
1214: it.remove();
1215: }
1216: }
1217:
1218: }
1219: }
1220: //TODO : repaint the column only
1221: this .repaint();
1222: }
1223:
1224: //Scrollable
1225: public Dimension getPreferredScrollableViewportSize() {
1226: return this .getPreferredSize();
1227: }
1228:
1229: public int getScrollableUnitIncrement(Rectangle visibleRect,
1230: int orientation, int direction) {
1231: if (orientation == SwingConstants.HORIZONTAL) {
1232: return this .tiledLayer.getTileWidth();
1233: }
1234: return this .tiledLayer.getTileHeight();
1235: }
1236:
1237: public int getScrollableBlockIncrement(Rectangle visibleRect,
1238: int orientation, int direction) {
1239: if (orientation == SwingConstants.HORIZONTAL) {
1240: return this .tiledLayer.getTileWidth();
1241: }
1242: return this .tiledLayer.getTileHeight();
1243: }
1244:
1245: public boolean getScrollableTracksViewportWidth() {
1246: return false;
1247: }
1248:
1249: public boolean getScrollableTracksViewportHeight() {
1250: return false;
1251: }
1252:
1253: private class HiliteAnimator extends TimerTask {
1254: private Color[] colors = { new Color(255, 255, 255),
1255: new Color(200, 200, 200), new Color(155, 155, 155),
1256: new Color(100, 100, 100), new Color(55, 55, 55),
1257: new Color(0, 0, 0), new Color(55, 55, 55),
1258: new Color(100, 100, 100), new Color(155, 155, 155),
1259: new Color(200, 200, 200), new Color(255, 255, 255), };
1260: private int i = 0;
1261:
1262: public void run() {
1263: synchronized (TiledLayerEditorComponent.this .cellsSelected) {
1264: if (++i >= colors.length) {
1265: i = 0;
1266: }
1267: TiledLayerEditorComponent.this .currentSelectedColor = colors[i];
1268: int[] bounds = TiledLayerEditorComponent.this
1269: .getVisibleCellBounds();
1270:
1271: for (int r = bounds[0]; r <= bounds[2]; r++) {
1272: for (int c = bounds[1]; c <= bounds[3]; c++) {
1273: Position cell = new Position(r, c);
1274: if (TiledLayerEditorComponent.this .cellsSelected
1275: .contains(cell)) {
1276: Rectangle rect = TiledLayerEditorComponent.this
1277: .getCellArea(cell);
1278:
1279: TiledLayerEditorComponent.this .repaint(
1280: rect.x, rect.y, rect.width,
1281: SELECTION_BORDER_WIDTH);
1282: TiledLayerEditorComponent.this
1283: .repaint(
1284: rect.x,
1285: rect.y,
1286: SELECTION_BORDER_WIDTH,
1287: rect.height
1288: - (TiledLayerEditorComponent.this .gridWidth * 2));
1289: TiledLayerEditorComponent.this
1290: .repaint(
1291: rect.x
1292: + (rect.width - SELECTION_BORDER_WIDTH),
1293: rect.y,
1294: SELECTION_BORDER_WIDTH,
1295: rect.height);
1296: TiledLayerEditorComponent.this
1297: .repaint(
1298: rect.x,
1299: rect.y
1300: + (rect.height - SELECTION_BORDER_WIDTH),
1301: rect.width,
1302: SELECTION_BORDER_WIDTH);
1303: }
1304: }
1305: }
1306: }
1307: }
1308: }
1309:
1310: private boolean isCellVisible(Position cell) {
1311: return this .getVisibleRect().intersects(this .getCellArea(cell));
1312: }
1313:
1314: private void updateHiLite(Point point) {
1315: Position oldHilited = this .cellHiLited;
1316: Position cell = this .getCellAtPoint(point);
1317: if (cell == null)
1318: return;
1319: //if (DEBUG) System.out.println("dragOver " + cell);
1320: if (!cell.equals(oldHilited)) {
1321: this .cellHiLited = cell;
1322: if (oldHilited != null) {
1323: this .repaint(this .getCellArea(oldHilited));
1324: }
1325: this .repaint(this .getCellArea(this .cellHiLited));
1326: }
1327: }
1328:
1329: //DnD implementation
1330: private class TiledLayerDropTargetListener implements
1331: DropTargetListener {
1332: public void dragEnter(DropTargetDragEvent dtde) {
1333: if (DEBUG)
1334: System.out.println("dragEnter"); // NOI18N
1335: }
1336:
1337: public void dragOver(DropTargetDragEvent dtde) {
1338: TiledLayerEditorComponent.this .updateHiLite(dtde
1339: .getLocation());
1340: }
1341:
1342: public void dropActionChanged(DropTargetDragEvent dtde) {
1343: if (DEBUG)
1344: System.out.println("dropActionChanged"); // NOI18N
1345: }
1346:
1347: public void dragExit(DropTargetEvent dte) {
1348: if (DEBUG)
1349: System.out.println("dragExit"); // NOI18N
1350: }
1351:
1352: public void drop(DropTargetDropEvent dtde) {
1353: Point dropPoint = dtde.getLocation();
1354: if (DEBUG)
1355: System.out.println("Start drop @: " + dropPoint); // NOI18N
1356: Transferable transferable = dtde.getTransferable();
1357: try {
1358: TileDataFlavor tileFlavor = new TileDataFlavor();
1359: if (transferable.isDataFlavorSupported(tileFlavor)) {
1360: dtde.acceptDrop(DnDConstants.ACTION_COPY);
1361: List<Tile> tiles = (List<Tile>) transferable
1362: .getTransferData(tileFlavor);
1363: assert (tiles.size() > 0);
1364: ImageResource imgRes = TiledLayerEditorComponent.this .tiledLayer
1365: .getImageResource();
1366: Tile newTile = imgRes.getTile(tiles.get(0)
1367: .getIndex(),
1368: TiledLayerEditorComponent.this .tiledLayer
1369: .getTileWidth(),
1370: TiledLayerEditorComponent.this .tiledLayer
1371: .getTileHeight(), false);
1372: Position cell = TiledLayerEditorComponent.this
1373: .getCellAtPoint(dropPoint);
1374: if (TiledLayerEditorComponent.this .cellsSelected
1375: .contains(cell)) {
1376: TiledLayerEditorComponent.this .tiledLayer
1377: .setTileAtPositions(
1378: newTile.getIndex(),
1379: TiledLayerEditorComponent.this .cellsSelected);
1380: } else {
1381: TiledLayerEditorComponent.this .tiledLayer
1382: .setTileAt(newTile.getIndex(), cell
1383: .getRow(), cell.getCol());
1384: }
1385: dtde.dropComplete(true);
1386: } else {
1387: if (DEBUG)
1388: System.out.println("NOT a Tile :("); // NOI18N
1389: dtde.dropComplete(false);
1390: }
1391: } catch (ClassNotFoundException e) {
1392: e.printStackTrace();
1393: dtde.dropComplete(false);
1394: } catch (UnsupportedFlavorException e) {
1395: e.printStackTrace();
1396: dtde.dropComplete(false);
1397: } catch (IOException e) {
1398: e.printStackTrace();
1399: dtde.dropComplete(false);
1400: }
1401: }
1402: }
1403:
1404: //TiledLayerListener
1405: public void tileChanged(TiledLayer tiledLayer, int row, int col) {
1406: this .repaint(this .getCellArea(row, col));
1407: }
1408:
1409: public void tilesChanged(TiledLayer tiledLayer, Set positions) {
1410: this .revalidate();
1411: this .repaint();
1412: }
1413:
1414: public void tilesStructureChanged(TiledLayer source) {
1415: if (DEBUG)
1416: System.out.println("tilesStructureChanged()");
1417: this .revalidate();
1418: this .repaint();
1419: }
1420:
1421: public void columnsInserted(TiledLayer tiledLayer, int index,
1422: int count) {
1423: this .shiftSelectedCellColumns(index, count);
1424: this .revalidate();
1425: this .repaint();
1426: this .rulerHorizontal.repaint();
1427: }
1428:
1429: public void columnsRemoved(TiledLayer tiledLayer, int index,
1430: int count) {
1431: this .shiftSelectedCellColumns(index, -count);
1432: this .trimSelectedCellsToSize();
1433: this .revalidate();
1434: this .repaint();
1435: this .rulerHorizontal.repaint();
1436: }
1437:
1438: public void rowsInserted(TiledLayer tiledLayer, int index, int count) {
1439: this .shiftSelectedCellRows(index, count);
1440: this .revalidate();
1441: this .repaint();
1442: this .rulerVertical.repaint();
1443: }
1444:
1445: public void rowsRemoved(TiledLayer tiledLayer, int index, int count) {
1446: this .shiftSelectedCellRows(index, -count);
1447: this .trimSelectedCellsToSize();
1448: this .revalidate();
1449: this .repaint();
1450: this .rulerVertical.repaint();
1451: }
1452:
1453: private void trimSelectedCellsToSize() {
1454: Set<Position> bucket = new HashSet<Position>();
1455: synchronized (cellsSelected) {
1456: for (Position cell : cellsSelected) {
1457: if (cell.getRow() >= tiledLayer.getRowCount()
1458: || cell.getCol() >= this .tiledLayer
1459: .getColumnCount()) {
1460: bucket.add(cell);
1461: }
1462: }
1463: cellsSelected.removeAll(bucket);
1464: }
1465: }
1466:
1467: private void shiftSelectedCellRows(int index, int count) {
1468:
1469: synchronized (this .cellsSelected) {
1470: List<Position> bucket = new ArrayList<Position>();
1471: for (Iterator<Position> it = cellsSelected.iterator(); it
1472: .hasNext();) {
1473: Position position = it.next();
1474: int curRow = position.getRow();
1475: if (curRow >= index) {
1476: it.remove();
1477: //System.out.println("Shifting row " + curRow + " to " + (curRow + count));
1478: bucket.add(new Position(curRow + count, position
1479: .getCol()));
1480: }
1481: }
1482:
1483: for (Position position : bucket) {
1484: this .cellsSelected.add(position);
1485: }
1486: }
1487: }
1488:
1489: private void shiftSelectedCellColumns(int index, int count) {
1490:
1491: synchronized (this .cellsSelected) {
1492: List<Position> bucket = new ArrayList<Position>();
1493: for (Iterator<Position> it = cellsSelected.iterator(); it
1494: .hasNext();) {
1495: Position position = it.next();
1496: int curCol = position.getCol();
1497: if (curCol >= index) {
1498: it.remove();
1499: //System.out.println("Shifting col " + curCol + " to " + (curCol + count));
1500: bucket.add(new Position(position.getRow(), curCol
1501: + count));
1502: }
1503: }
1504:
1505: for (Position position : bucket) {
1506: this .cellsSelected.add(position);
1507: }
1508: }
1509: }
1510:
1511: private GridButton gridButton = new GridButton();
1512:
1513: public JComponent getGridButton() {
1514: return this .gridButton;
1515: }
1516:
1517: private class GridButton extends JComponent implements
1518: MouseListener {
1519: private static final int BORDER = 2;
1520:
1521: public GridButton() {
1522: ToolTipManager.sharedInstance().registerComponent(this );
1523: this .addMouseListener(this );
1524: }
1525:
1526: @Override
1527: public String getToolTipText() {
1528: return NbBundle.getMessage(TiledLayerEditorComponent.class,
1529: "TiledLayerEditorComponent.GridButton.tooltip");
1530: }
1531:
1532: @Override
1533: protected void paintComponent(Graphics g) {
1534: g.setColor(new Color(230, 230, 255));
1535: g.fillRect(0, 0, this .getWidth(), this .getHeight());
1536: g.setColor(Color.BLACK);
1537: int startx = BORDER;
1538: int starty = BORDER;
1539: int x = startx;
1540: int y = starty;
1541: int w = this .getWidth() - (2 * BORDER);
1542: int h = this .getHeight() - (2 * BORDER);
1543: if (TiledLayerEditorComponent.this .gridWidth > 0) {
1544: if (TiledLayerEditorComponent.this .gridMode == GRID_MODE_DOTS) {
1545: g.setColor(Color.GRAY);
1546: }
1547: int offX = w / 2;
1548: int offY = h / 2;
1549:
1550: x += offX;
1551: g.drawLine(x, starty, x, starty + h);
1552:
1553: y += offY;
1554: g.drawLine(startx, y, startx + w, y);
1555:
1556: }
1557: g.setColor(Color.BLACK);
1558: g.drawRoundRect(startx, starty, w, h, BORDER, BORDER);
1559: }
1560:
1561: public void mouseClicked(MouseEvent e) {
1562: byte mode = TiledLayerEditorComponent.this .gridMode;
1563: if (mode == GRID_MODE_LINES) {
1564: if (TiledLayerEditorComponent.this .gridWidth == 0) {
1565: TiledLayerEditorComponent.this
1566: .setGridMode(GRID_MODE_DOTS);
1567: } else {
1568: TiledLayerEditorComponent.this .gridWidth = 0;
1569: }
1570: } else {
1571: TiledLayerEditorComponent.this
1572: .setGridMode(GRID_MODE_LINES);
1573: TiledLayerEditorComponent.this .gridWidth = 1;
1574: }
1575: this .repaint();
1576: TiledLayerEditorComponent.this .rulerHorizontal.repaint();
1577: TiledLayerEditorComponent.this .rulerVertical.repaint();
1578: TiledLayerEditorComponent.this .repaint();
1579: }
1580:
1581: public void mouseEntered(MouseEvent e) {
1582: }
1583:
1584: public void mouseExited(MouseEvent e) {
1585: }
1586:
1587: public void mousePressed(MouseEvent e) {
1588: }
1589:
1590: public void mouseReleased(MouseEvent e) {
1591: }
1592: }
1593:
1594: class RulerVertical extends JComponent implements MouseListener,
1595: MouseMotionListener {
1596: private static final int SIZE = 14;
1597: private static final boolean DEBUG = false;
1598:
1599: private Set<Integer> pressed = new HashSet<Integer>();
1600:
1601: private int hilitedRowHeader = -1;
1602:
1603: public RulerVertical() {
1604: ToolTipManager.sharedInstance().registerComponent(this );
1605: this .addMouseListener(this );
1606: this .addMouseMotionListener(this );
1607: }
1608:
1609: public String getToolTipText(MouseEvent event) {
1610: return NbBundle.getMessage(TiledLayerEditorComponent.class,
1611: "TiledLayerEditorComponent.verticalRuler.tooltip",
1612: this .getRowAtPoint(event.getPoint()));
1613: //return "Row: " + this.getRowAtPoint(event.getPoint());
1614: }
1615:
1616: public Dimension getPreferredSize() {
1617: Dimension size = TiledLayerEditorComponent.this
1618: .getPreferredSize();
1619: size.width = SIZE;
1620: return size;
1621: }
1622:
1623: protected void paintComponent(Graphics graphincs) {
1624: Graphics2D g = (Graphics2D) graphincs;
1625:
1626: Rectangle rect = g.getClipBounds();
1627: g.setColor(Color.WHITE);
1628: g.fill(rect);
1629: if (DEBUG)
1630: System.out.println("RulerVertical.repaint " + rect); // NOI18N
1631:
1632: int unit = TiledLayerEditorComponent.this .gridWidth
1633: + TiledLayerEditorComponent.this .cellHeight;
1634:
1635: for (int y = (rect.y / unit) * unit; y <= rect.y
1636: + rect.height; y += unit) {
1637: int row = y / unit;
1638:
1639: //only paint header cells for existing rows
1640: if (row >= TiledLayerEditorComponent.this .tiledLayer
1641: .getRowCount())
1642: break;
1643:
1644: boolean raised = true;
1645: g.setColor(new Color(240, 238, 230));
1646:
1647: if (this .pressed.contains(row)) {
1648: g.setColor(new Color(200, 200, 200));
1649: raised = false;
1650: }
1651:
1652: g.fill3DRect(0, y
1653: + TiledLayerEditorComponent.this .gridWidth / 2,
1654: SIZE, unit, raised);
1655:
1656: if (row == this .hilitedRowHeader) {
1657: g.setColor(HILITE_COLOR);
1658: g.fill3DRect(0, y
1659: + TiledLayerEditorComponent.this .gridWidth
1660: / 2, SIZE, unit, raised);
1661: }
1662: }
1663: }
1664:
1665: private int getRowAtPoint(Point point) {
1666: return this .getRowAtCoordinates(point.x, point.y);
1667: }
1668:
1669: private int getRowAtCoordinates(int x, int y) {
1670: return (y - TiledLayerEditorComponent.this .gridWidth)
1671: / (TiledLayerEditorComponent.this .cellHeight + TiledLayerEditorComponent.this .gridWidth);
1672: }
1673:
1674: private Rectangle getRowHeaderArea(int row) {
1675: Rectangle area = new Rectangle(
1676: 0,
1677: ((TiledLayerEditorComponent.this .cellHeight + TiledLayerEditorComponent.this .gridWidth) * row)
1678: + TiledLayerEditorComponent.this .gridWidth
1679: / 2, SIZE,
1680: TiledLayerEditorComponent.this .cellHeight
1681: + TiledLayerEditorComponent.this .gridWidth);
1682: return area;
1683: }
1684:
1685: private void hiliteRowHeader(int row) {
1686: if (this .hilitedRowHeader == row) {
1687: return;
1688: }
1689: int oldHilited = this .hilitedRowHeader;
1690: this .hilitedRowHeader = row;
1691: this .repaint(this .getRowHeaderArea(row));
1692: this .repaint(this .getRowHeaderArea(oldHilited));
1693: }
1694:
1695: /**
1696: * Toggle the selection of the column header and the column cell selection.
1697: */
1698: public void mouseClicked(MouseEvent e) {
1699: int row = this .getRowAtPoint(e.getPoint());
1700: if (TiledLayerEditorComponent.this .isRowSelected(row)) {
1701: TiledLayerEditorComponent.this .setRowSelection(row,
1702: false);
1703: } else {
1704: TiledLayerEditorComponent.this .setRowSelection(row,
1705: true);
1706: }
1707: this .repaint(this .getRowHeaderArea(row));
1708: }
1709:
1710: public void mousePressed(MouseEvent e) {
1711: int row = this .getRowAtPoint(e.getPoint());
1712: if (e.isPopupTrigger()) {
1713: this .handlePopUp(e);
1714: } else {
1715: this .pressed.add(row);
1716: this .repaint(this .getRowHeaderArea(row));
1717: }
1718: }
1719:
1720: public void mouseReleased(MouseEvent e) {
1721: if (e.isPopupTrigger()) {
1722: this .handlePopUp(e);
1723: } else {
1724: this .pressed.clear();
1725: this .repaint();
1726: }
1727: }
1728:
1729: public void mouseEntered(MouseEvent e) {
1730: }
1731:
1732: public void mouseExited(MouseEvent e) {
1733: this .hiliteRowHeader(-1);
1734: }
1735:
1736: public void mouseDragged(MouseEvent e) {
1737: }
1738:
1739: public void mouseMoved(MouseEvent e) {
1740: int row = this .getRowAtPoint(e.getPoint());
1741: this .hiliteRowHeader(row);
1742: }
1743:
1744: private void handlePopUp(MouseEvent e) {
1745: int row = this .getRowAtPoint(e.getPoint());
1746: if (DEBUG)
1747: System.out.println("Popup row: " + row); // NOI18N
1748: JPopupMenu menu = this .createRulerPopupMenu(row);
1749: menu.show(this , e.getX(), e.getY());
1750: }
1751:
1752: private JPopupMenu createRulerPopupMenu(int row) {
1753: JPopupMenu menu = new JPopupMenu();
1754: for (Iterator iter = this .getActions().iterator(); iter
1755: .hasNext();) {
1756: Action action = (Action) iter.next();
1757: action.putValue("ROW", new Integer(row)); // NOI18N
1758: menu.add(action);
1759: }
1760: return menu;
1761: }
1762:
1763: public List<Action> getActions() {
1764: List<Action> actions = new ArrayList<Action>();
1765: actions.add(new DeleteRowAction());
1766: actions.add(new PrependRowAction());
1767: actions.add(new AppendRowAction());
1768: return Collections.unmodifiableList(actions);
1769: }
1770:
1771: private class DeleteRowAction extends AbstractAction {
1772: {
1773: this
1774: .putValue(
1775: NAME,
1776: NbBundle
1777: .getMessage(
1778: TiledLayerEditorComponent.class,
1779: "TiledLayerEditorComponent.verticalRuler.actionDeleteRow.txt"));
1780: }
1781:
1782: public void actionPerformed(ActionEvent e) {
1783: int row = ((Integer) this .getValue("ROW")).intValue(); // NOI18N
1784: TiledLayerEditorComponent.this .tiledLayer.deleteRows(
1785: row, 1);
1786: }
1787: }
1788:
1789: private class PrependRowAction extends AbstractAction {
1790: {
1791: this
1792: .putValue(
1793: NAME,
1794: NbBundle
1795: .getMessage(
1796: TiledLayerEditorComponent.class,
1797: "TiledLayerEditorComponent.verticalRuler.actionPrependRow.txt"));
1798: }
1799:
1800: public void actionPerformed(ActionEvent e) {
1801: int row = ((Integer) this .getValue("ROW")).intValue(); // NOI18N
1802: TiledLayerEditorComponent.this .tiledLayer.insertRows(
1803: row, 1);
1804: }
1805: }
1806:
1807: private class AppendRowAction extends AbstractAction {
1808: {
1809: this
1810: .putValue(
1811: NAME,
1812: NbBundle
1813: .getMessage(
1814: TiledLayerEditorComponent.class,
1815: "TiledLayerEditorComponent.verticalRuler.actionAppendRow.txt"));
1816: }
1817:
1818: public void actionPerformed(ActionEvent e) {
1819: int row = ((Integer) this .getValue("ROW")).intValue(); // NOI18N
1820: TiledLayerEditorComponent.this .tiledLayer.insertRows(
1821: row + 1, 1);
1822: }
1823: }
1824: }
1825:
1826: class RulerHorizontal extends JComponent implements MouseListener,
1827: MouseMotionListener {
1828: private static final int SIZE = 14;
1829: private static final boolean DEBUG = false;
1830:
1831: private Set<Integer> pressed = new HashSet<Integer>();
1832:
1833: private int hilitedColumnHeader = -1;
1834:
1835: public RulerHorizontal() {
1836: ToolTipManager.sharedInstance().registerComponent(this );
1837: this .addMouseListener(this );
1838: this .addMouseMotionListener(this );
1839: }
1840:
1841: public String getToolTipText(MouseEvent event) {
1842: return NbBundle
1843: .getMessage(
1844: TiledLayerEditorComponent.class,
1845: "TiledLayerEditorComponent.horizontalRuler.tooltip",
1846: this .getColumnAtPoint(event.getPoint()));
1847: //return "Column: " + this.getColumnAtPoint(event.getPoint());
1848: }
1849:
1850: public Dimension getPreferredSize() {
1851: Dimension size = TiledLayerEditorComponent.this
1852: .getPreferredSize();
1853: size.height = SIZE;
1854: return size;
1855: }
1856:
1857: protected void paintComponent(Graphics graphincs) {
1858: Graphics2D g = (Graphics2D) graphincs;
1859:
1860: Rectangle rect = g.getClipBounds();
1861: g.setColor(Color.WHITE);
1862: g.fill(rect);
1863:
1864: if (DEBUG)
1865: System.out.println("RulerHorizontal.repaint " + rect); // NOI18N
1866:
1867: int unit = TiledLayerEditorComponent.this .gridWidth
1868: + TiledLayerEditorComponent.this .cellWidth;
1869:
1870: for (int x = (rect.x / unit) * unit; x <= rect.x
1871: + rect.width; x += unit) {
1872: int col = x / unit;
1873:
1874: if (col >= TiledLayerEditorComponent.this .tiledLayer
1875: .getColumnCount()) {
1876: break;
1877: }
1878:
1879: boolean raised = true;
1880: //if (DEBUG) System.out.println("paint col: " + col);
1881: g.setColor(new Color(240, 238, 230));
1882:
1883: if (this .pressed.contains(col)) {
1884: g.setColor(new Color(200, 200, 200));
1885: raised = false;
1886: }
1887:
1888: g.fill3DRect(x
1889: + TiledLayerEditorComponent.this .gridWidth / 2,
1890: 0, unit, SIZE, raised);
1891:
1892: if (col == this .hilitedColumnHeader) {
1893: g.setColor(HILITE_COLOR);
1894: g.fill3DRect(x
1895: + TiledLayerEditorComponent.this .gridWidth
1896: / 2, 0, unit, SIZE, raised);
1897: }
1898: }
1899: }
1900:
1901: private int getColumnAtPoint(Point point) {
1902: return this .getColumnAtCoordinates(point.x, point.y);
1903: }
1904:
1905: private int getColumnAtCoordinates(int x, int y) {
1906: return (x - TiledLayerEditorComponent.this .gridWidth)
1907: / (TiledLayerEditorComponent.this .cellWidth + TiledLayerEditorComponent.this .gridWidth);
1908: }
1909:
1910: private Rectangle getColumnHeaderArea(int col) {
1911: Rectangle area = new Rectangle(
1912: ((TiledLayerEditorComponent.this .cellWidth + TiledLayerEditorComponent.this .gridWidth) * col)
1913: + TiledLayerEditorComponent.this .gridWidth
1914: / 2, 0,
1915: TiledLayerEditorComponent.this .cellWidth
1916: + TiledLayerEditorComponent.this .gridWidth,
1917: SIZE);
1918: return area;
1919: }
1920:
1921: private void hiliteColumnHeader(int col) {
1922: if (this .hilitedColumnHeader == col) {
1923: return;
1924: }
1925: int oldHilited = this .hilitedColumnHeader;
1926: this .hilitedColumnHeader = col;
1927: this .repaint(this .getColumnHeaderArea(col));
1928: this .repaint(this .getColumnHeaderArea(oldHilited));
1929: }
1930:
1931: /**
1932: * Toggle the selection of the column header and the column cell selection.
1933: */
1934: public void mouseClicked(MouseEvent e) {
1935: int col = this .getColumnAtPoint(e.getPoint());
1936: if (TiledLayerEditorComponent.this .isColumnsSelected(col)) {
1937: TiledLayerEditorComponent.this .setColumnSelection(col,
1938: false);
1939: } else {
1940: TiledLayerEditorComponent.this .setColumnSelection(col,
1941: true);
1942: }
1943: }
1944:
1945: public void mousePressed(MouseEvent e) {
1946: int col = this .getColumnAtPoint(e.getPoint());
1947: if (e.isPopupTrigger()) {
1948: this .handlePopUp(e);
1949: } else {
1950: this .pressed.add(col);
1951: this .repaint(this .getColumnHeaderArea(col));
1952: }
1953: }
1954:
1955: public void mouseReleased(MouseEvent e) {
1956: int col = this .getColumnAtPoint(e.getPoint());
1957: if (e.isPopupTrigger()) {
1958: this .handlePopUp(e);
1959: } else {
1960: this .pressed.clear();
1961: this .repaint();
1962: }
1963: }
1964:
1965: public void mouseEntered(MouseEvent e) {
1966: }
1967:
1968: public void mouseExited(MouseEvent e) {
1969: this .hiliteColumnHeader(-1);
1970: }
1971:
1972: public void mouseDragged(MouseEvent e) {
1973: }
1974:
1975: public void mouseMoved(MouseEvent e) {
1976: int col = this .getColumnAtPoint(e.getPoint());
1977: this .hiliteColumnHeader(col);
1978: }
1979:
1980: private void handlePopUp(MouseEvent e) {
1981: int col = this .getColumnAtPoint(e.getPoint());
1982: if (DEBUG)
1983: System.out.println("Popup col: " + col); // NOI18N
1984: JPopupMenu menu = this .createRulerPopupMenu(col);
1985: menu.show(this , e.getX(), e.getY());
1986: this .hiliteColumnHeader(col);
1987: }
1988:
1989: private JPopupMenu createRulerPopupMenu(int col) {
1990: JPopupMenu menu = new JPopupMenu();
1991: for (Iterator iter = this .getActions().iterator(); iter
1992: .hasNext();) {
1993: Action action = (Action) iter.next();
1994: action.putValue("COLUMN", new Integer(col)); // NOI18N
1995: menu.add(action);
1996: }
1997: return menu;
1998: }
1999:
2000: public List getActions() {
2001: List<Action> actions = new ArrayList<Action>();
2002: actions.add(new DeleteColAction());
2003: actions.add(new PrependColAction());
2004: actions.add(new AppendColAction());
2005: return Collections.unmodifiableList(actions);
2006: }
2007:
2008: private class DeleteColAction extends AbstractAction {
2009: {
2010: this
2011: .putValue(
2012: NAME,
2013: NbBundle
2014: .getMessage(
2015: TiledLayerEditorComponent.class,
2016: "TiledLayerEditorComponent.horizontalRuler.actionDeleteCol.txt"));
2017: }
2018:
2019: public void actionPerformed(ActionEvent e) {
2020: int col = ((Integer) this .getValue("COLUMN"))
2021: .intValue(); // NOI18N
2022: TiledLayerEditorComponent.this .tiledLayer
2023: .deleteColumns(col, 1);
2024: }
2025: }
2026:
2027: private class PrependColAction extends AbstractAction {
2028: {
2029: this
2030: .putValue(
2031: NAME,
2032: NbBundle
2033: .getMessage(
2034: TiledLayerEditorComponent.class,
2035: "TiledLayerEditorComponent.horizontalRuler.actionPrependCol.txt"));
2036: }
2037:
2038: public void actionPerformed(ActionEvent e) {
2039: int col = ((Integer) this .getValue("COLUMN"))
2040: .intValue(); // NOI18N
2041: TiledLayerEditorComponent.this .tiledLayer
2042: .insertColumns(col, 1);
2043: }
2044: }
2045:
2046: private class AppendColAction extends AbstractAction {
2047: {
2048: this
2049: .putValue(
2050: NAME,
2051: NbBundle
2052: .getMessage(
2053: TiledLayerEditorComponent.class,
2054: "TiledLayerEditorComponent.horizontalRuler.actionAppendCol.txt"));
2055: }
2056:
2057: public void actionPerformed(ActionEvent e) {
2058: int col = ((Integer) this .getValue("COLUMN"))
2059: .intValue(); // NOI18N
2060: TiledLayerEditorComponent.this .tiledLayer
2061: .insertColumns(col + 1, 1);
2062: }
2063: }
2064: }
2065:
2066: }
|